8315810: Reimplement sun.reflect.ReflectionFactory::newConstructorForSerialization with method handles

Co-authored-by: Chen Liang <liach@openjdk.org>
Reviewed-by: rriggs
This commit is contained in:
Mandy Chung 2023-09-14 16:10:55 +00:00
parent eb1f67b160
commit 5cea53d372
10 changed files with 141 additions and 41 deletions

View file

@ -1034,12 +1034,12 @@ public final class ObjectStreamClass implements Serializable {
new AccessControlContext(domains));
} catch (UndeclaredThrowableException x) {
Throwable cause = x.getCause();
if (cause instanceof InstantiationException)
throw (InstantiationException) cause;
if (cause instanceof InvocationTargetException)
throw (InvocationTargetException) cause;
if (cause instanceof IllegalAccessException)
throw (IllegalAccessException) cause;
if (cause instanceof InstantiationException ie)
throw ie;
if (cause instanceof InvocationTargetException ite)
throw ite;
if (cause instanceof IllegalAccessException iae)
throw iae;
// not supposed to happen
throw x;
}
@ -1047,6 +1047,12 @@ public final class ObjectStreamClass implements Serializable {
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
throw new InternalError(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof Error err)
throw err;
else
throw ex;
} catch (InstantiationError err) {
var ex = new InstantiationException();
ex.initCause(err);

View file

@ -128,12 +128,11 @@ sealed class DirectMethodHandle extends MethodHandle {
}
static DirectMethodHandle make(MemberName member) {
if (member.isConstructor())
return makeAllocator(member);
return makeAllocator(member.getDeclaringClass(), member);
return make(member.getDeclaringClass(), member);
}
private static DirectMethodHandle makeAllocator(MemberName ctor) {
static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
Class<?> instanceClass = ctor.getDeclaringClass();
ctor = ctor.asConstructor();
assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);

View file

@ -1647,6 +1647,12 @@ abstract class MethodHandleImpl {
public Class<?>[] exceptionTypes(MethodHandle handle) {
return VarHandles.exceptionTypes(handle);
}
@Override
public MethodHandle serializableConstructor(Class<?> decl, Constructor<?> ctorToCall) throws IllegalAccessException {
return IMPL_LOOKUP.serializableConstructor(decl, ctorToCall);
}
});
}

View file

@ -3525,6 +3525,33 @@ return mh1;
return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
}
/*
* Produces a method handle that is capable of creating instances of the given class
* and instantiated by the given constructor. No security manager check.
*
* This method should only be used by ReflectionFactory::newConstructorForSerialization.
*/
/* package-private */ MethodHandle serializableConstructor(Class<?> decl, Constructor<?> c) throws IllegalAccessException {
MemberName ctor = new MemberName(c);
assert(ctor.isConstructor() && constructorInSuperclass(decl, c));
checkAccess(REF_newInvokeSpecial, decl, ctor);
assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here
return DirectMethodHandle.makeAllocator(decl, ctor).setVarargs(ctor);
}
private static boolean constructorInSuperclass(Class<?> decl, Constructor<?> ctor) {
if (decl == ctor.getDeclaringClass())
return true;
Class<?> cl = decl;
while ((cl = cl.getSuperclass()) != null) {
if (cl == ctor.getDeclaringClass()) {
return true;
}
}
return false;
}
/**
* Produces a method handle giving read access to a reflected field.
* The type of the method handle will have a return type of the field's