diff --git a/ObjectLayout/pom.xml b/ObjectLayout/pom.xml
index 504fb8e..48d3666 100644
--- a/ObjectLayout/pom.xml
+++ b/ObjectLayout/pom.xml
@@ -65,7 +65,7 @@
maven-surefire-plugin
2.12.4
- -Xmx1g
+ -Xmx1g -Xbootclasspath/a:${basedir}/target/classes
false
diff --git a/ObjectLayout/src/main/java/org/ObjectLayout/AbstractIntrinsicObjectModel.java b/ObjectLayout/src/main/java/org/ObjectLayout/AbstractIntrinsicObjectModel.java
index 1445186..27a20c7 100644
--- a/ObjectLayout/src/main/java/org/ObjectLayout/AbstractIntrinsicObjectModel.java
+++ b/ObjectLayout/src/main/java/org/ObjectLayout/AbstractIntrinsicObjectModel.java
@@ -45,6 +45,14 @@ Class getObjectClass() {
return objectClass;
}
+ Class getContainingClass() {
+ return containingClass;
+ }
+
+ Field getField() {
+ return field;
+ }
+
private void sanityCheckAtModelConstruction() {
if ((primitiveArrayModel != null) &&
!primitiveArrayModel._getArrayClass().equals(objectClass)) {
@@ -141,7 +149,8 @@ final void _sanityCheckInstantiation(final Object containingObject) {
try {
if (field.get(containingObject) != null) {
throw new IllegalStateException("Intrinsic object field \"" + field.getName() +
- "\" in containing object is already initialized");
+ "\" in containing object " + containingObject + " is already initialized to " +
+ field.get(containingObject));
}
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
diff --git a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjectModel.java b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjectModel.java
index d1770bd..7b66a95 100644
--- a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjectModel.java
+++ b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjectModel.java
@@ -34,9 +34,13 @@ final class IntrinsicObjectModel extends AbstractIntrinsicObjectModel {
*/
final T constructWithin(final Object containingObject) {
try {
+ Constructor ctor = getObjectClass().getDeclaredConstructor();
+ if (!ctor.isAccessible()) {
+ ctor.setAccessible(true);
+ }
return instantiate(
containingObject,
- getObjectClass().getDeclaredConstructor(),
+ ctor,
(Object[]) null
);
} catch (NoSuchMethodException ex) {
diff --git a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjects.java b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjects.java
index 13a074d..c5e32e1 100644
--- a/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjects.java
+++ b/ObjectLayout/src/main/java/org/ObjectLayout/IntrinsicObjects.java
@@ -12,6 +12,9 @@
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
/**
* Intrinsic objects (declared with the {@link org.ObjectLayout.Intrinsic @Intrisic} annotation) may have
* their layout within the containing object instance optimized by JDK implementations, such that access
@@ -55,10 +58,24 @@ private IntrinsicObjects() {
* @param containingObject The object instance that will contain this intrinsic object
* @return A reference to the the newly constructed intrinsic object
*/
+ @CallerSensitive
+ @SuppressWarnings("restriction")
public static T constructWithin(
final String fieldName,
- final Object containingObject) {
+ final Object containingObject) throws IllegalArgumentException {
+
+ // First we do some plausibility/security checks
+ Class> caller = Reflection.getCallerClass();
+ if (!containingObject.getClass().equals(caller))
+ throw new IllegalArgumentException();
+
IntrinsicObjectModel model = lookupModelFor(fieldName, containingObject);
+
+ // Check if our caller is allowed to access the constructor.
+ // We wrap the "IllegalAccessException" in an unchecked "IllegalArgumentException"
+ // to avoid try/catch clauses around every call to "constructWithin"
+ sanityCheckAccessRights(caller, model.getObjectClass(), null);
+
return model.constructWithin(containingObject);
}
@@ -75,12 +92,26 @@ public static T constructWithin(
* @param args the arguments to be used with the objectConstructor
* @return A reference to the the newly constructed intrinsic object
*/
+ @CallerSensitive
+ @SuppressWarnings("restriction")
public static T constructWithin(
final String fieldName,
final Object containingObject,
final Constructor objectConstructor,
final Object... args) {
+
+ // First we do some plausibility/security checks
+ Class> caller = Reflection.getCallerClass();
+ if (!containingObject.getClass().equals(caller))
+ throw new IllegalArgumentException();
+
IntrinsicObjectModel model = lookupModelFor(fieldName, containingObject);
+
+ // Check if our caller is allowed to access the constructor.
+ // We wrap the "IllegalAccessException" in an unchecked "IllegalArgumentException"
+ // to avoid try/catch clauses around every call to "constructWithin"
+ sanityCheckAccessRights(caller, model.getObjectClass(), objectConstructor);
+
return model.constructWithin(containingObject, objectConstructor, args);
}
@@ -339,4 +370,20 @@ private static void sanityCheckAnnotation(Intrinsic intrinsicAnnotation, Cla
}
}
}
+
+ @SuppressWarnings("restriction")
+ private static void sanityCheckAccessRights(Class> caller, Class field, Constructor ctor) {
+ // Check if our caller is allowed to access the constructor.
+ // We wrap the "IllegalAccessException" in an unchecked "IllegalArgumentException"
+ // to avoid try/catch clauses around every call to "constructWithin"
+ try {
+ if (ctor == null)
+ ctor = field.getDeclaredConstructor();
+ Reflection.ensureMemberAccess(caller, field, ctor, ctor.getModifiers());
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
}