Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ObjectLayout/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>-Xmx1g</argLine>
<argLine>-Xmx1g -Xbootclasspath/a:${basedir}/target/classes</argLine>
<enableAssertions>false</enableAssertions>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ Class<T> getObjectClass() {
return objectClass;
}

Class<T> getContainingClass() {
return containingClass;
}

Field getField() {
return field;
}

private void sanityCheckAtModelConstruction() {
if ((primitiveArrayModel != null) &&
!primitiveArrayModel._getArrayClass().equals(objectClass)) {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ final class IntrinsicObjectModel<T> extends AbstractIntrinsicObjectModel<T> {
*/
final T constructWithin(final Object containingObject) {
try {
Constructor<T> ctor = getObjectClass().getDeclaredConstructor();
if (!ctor.isAccessible()) {
ctor.setAccessible(true);
}
return instantiate(
containingObject,
getObjectClass().getDeclaredConstructor(),
ctor,
(Object[]) null
);
} catch (NoSuchMethodException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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> 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<T> 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);
}

Expand All @@ -75,12 +92,26 @@ public static <T> 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> T constructWithin(
final String fieldName,
final Object containingObject,
final Constructor<T> objectConstructor,
final Object... args) {

// First we do some plausibility/security checks
Class<?> caller = Reflection.getCallerClass();
if (!containingObject.getClass().equals(caller))
throw new IllegalArgumentException();

IntrinsicObjectModel<T> 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);
}

Expand Down Expand Up @@ -339,4 +370,20 @@ private static <T> void sanityCheckAnnotation(Intrinsic intrinsicAnnotation, Cla
}
}
}

@SuppressWarnings("restriction")
private static <T> void sanityCheckAccessRights(Class<?> caller, Class<T> field, Constructor<T> 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);
}
}
}