8336934: Clean up JavaLangReflectAccess

Reviewed-by: rriggs, darcy
This commit is contained in:
Chen Liang 2024-08-21 01:05:41 +00:00
parent d72810794b
commit 88ccbb6091
6 changed files with 35 additions and 168 deletions

View file

@ -165,6 +165,14 @@ public final class Constructor<T> extends Executable {
return res; return res;
} }
// Creates a new root constructor with a custom accessor for serialization hooks.
Constructor<T> newWithAccessor(ConstructorAccessor accessor) {
var res = new Constructor<>(clazz, parameterTypes, exceptionTypes, modifiers, slot,
signature, annotations, parameterAnnotations);
res.constructorAccessor = accessor;
return res;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View file

@ -173,21 +173,6 @@ public final class Method extends Executable {
return res; return res;
} }
/**
* Make a copy of a leaf method.
*/
Method leafCopy() {
if (this.root == null)
throw new IllegalArgumentException("Can only leafCopy a non-root Method");
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot, signature,
annotations, parameterAnnotations, annotationDefault);
res.root = root;
res.methodAccessor = methodAccessor;
return res;
}
/** /**
* @throws InaccessibleObjectException {@inheritDoc} * @throws InaccessibleObjectException {@inheritDoc}
* @throws SecurityException {@inheritDoc} * @throws SecurityException {@inheritDoc}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,65 +25,15 @@
package java.lang.reflect; package java.lang.reflect;
import jdk.internal.reflect.MethodAccessor; import jdk.internal.access.JavaLangReflectAccess;
import jdk.internal.reflect.ConstructorAccessor; import jdk.internal.reflect.ConstructorAccessor;
/** Package-private class implementing the /** Package-private class implementing the
jdk.internal.access.JavaLangReflectAccess interface, allowing the java.lang jdk.internal.access.JavaLangReflectAccess interface, allowing the java.lang
package to instantiate objects in this package. */ package to instantiate objects in this package. */
final class ReflectAccess implements JavaLangReflectAccess {
class ReflectAccess implements jdk.internal.access.JavaLangReflectAccess { public <T> Constructor<T> newConstructorWithAccessor(Constructor<T> original, ConstructorAccessor accessor) {
public <T> Constructor<T> newConstructor(Class<T> declaringClass, return original.newWithAccessor(accessor);
Class<?>[] parameterTypes,
Class<?>[] checkedExceptions,
int modifiers,
int slot,
String signature,
byte[] annotations,
byte[] parameterAnnotations)
{
return new Constructor<>(declaringClass,
parameterTypes,
checkedExceptions,
modifiers,
slot,
signature,
annotations,
parameterAnnotations);
}
public MethodAccessor getMethodAccessor(Method m) {
return m.getMethodAccessor();
}
public void setMethodAccessor(Method m, MethodAccessor accessor) {
m.setMethodAccessor(accessor);
}
public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
return c.getConstructorAccessor();
}
public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor)
{
c.setConstructorAccessor(accessor);
}
public int getConstructorSlot(Constructor<?> c) {
return c.getSlot();
}
public String getConstructorSignature(Constructor<?> c) {
return c.getSignature();
}
public byte[] getConstructorAnnotations(Constructor<?> c) {
return c.getRawAnnotations();
}
public byte[] getConstructorParameterAnnotations(Constructor<?> c) {
return c.getRawParameterAnnotations();
} }
public byte[] getExecutableTypeAnnotationBytes(Executable ex) { public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
@ -105,9 +55,6 @@ class ReflectAccess implements jdk.internal.access.JavaLangReflectAccess {
public Method copyMethod(Method arg) { public Method copyMethod(Method arg) {
return arg.copy(); return arg.copy();
} }
public Method leafCopyMethod(Method arg) {
return arg.leafCopy();
}
public Field copyField(Field arg) { public Field copyField(Field arg) {
return arg.copy(); return arg.copy();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,67 +29,29 @@ import java.lang.reflect.*;
import jdk.internal.reflect.*; import jdk.internal.reflect.*;
/** An interface which gives privileged packages Java-level access to /** An interface which gives privileged packages Java-level access to
internals of java.lang.reflect. */ internals of java.lang.reflect. Use as a last resort! */
public interface JavaLangReflectAccess { public interface JavaLangReflectAccess {
/** Creates a new java.lang.reflect.Constructor. Access checks as /**
per java.lang.reflect.AccessibleObject are not overridden. */ * Creates a new root constructor from the original one, with
public <T> Constructor<T> newConstructor(Class<T> declaringClass, * a custom accessor. Used by serialization hooks.
Class<?>[] parameterTypes, */
Class<?>[] checkedExceptions, <T> Constructor<T> newConstructorWithAccessor(Constructor<T> original, ConstructorAccessor accessor);
int modifiers,
int slot,
String signature,
byte[] annotations,
byte[] parameterAnnotations);
/** Gets the MethodAccessor object for a java.lang.reflect.Method */
public MethodAccessor getMethodAccessor(Method m);
/** Sets the MethodAccessor object for a java.lang.reflect.Method */
public void setMethodAccessor(Method m, MethodAccessor accessor);
/** Gets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
public ConstructorAccessor getConstructorAccessor(Constructor<?> c);
/** Sets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor);
/** Gets the byte[] that encodes TypeAnnotations on an Executable. */ /** Gets the byte[] that encodes TypeAnnotations on an Executable. */
public byte[] getExecutableTypeAnnotationBytes(Executable ex); public byte[] getExecutableTypeAnnotationBytes(Executable ex);
/** Gets the "slot" field from a Constructor (used for serialization) */
public int getConstructorSlot(Constructor<?> c);
/** Gets the "signature" field from a Constructor (used for serialization) */
public String getConstructorSignature(Constructor<?> c);
/** Gets the "annotations" field from a Constructor (used for serialization) */
public byte[] getConstructorAnnotations(Constructor<?> c);
/** Gets the "parameterAnnotations" field from a Constructor (used for serialization) */
public byte[] getConstructorParameterAnnotations(Constructor<?> c);
/** Gets the shared array of parameter types of an Executable. */ /** Gets the shared array of parameter types of an Executable. */
public Class<?>[] getExecutableSharedParameterTypes(Executable ex); public Class<?>[] getExecutableSharedParameterTypes(Executable ex);
/** Gets the shared array of exception types of an Executable. */ /** Gets the shared array of exception types of an Executable. */
public Class<?>[] getExecutableSharedExceptionTypes(Executable ex); public Class<?>[] getExecutableSharedExceptionTypes(Executable ex);
//
// Copying routines, needed to quickly fabricate new Field, // Copying routines, needed to quickly fabricate new Field,
// Method, and Constructor objects from templates // Method, and Constructor objects from templates
//
/** Makes a "child" copy of a Method */ /** Makes a "child" copy of a Method */
public Method copyMethod(Method arg); public Method copyMethod(Method arg);
/** Makes a copy of this non-root a Method */
public Method leafCopyMethod(Method arg);
/** Makes a "child" copy of a Field */ /** Makes a "child" copy of a Field */
public Field copyField(Field arg); public Field copyField(Field arg);

View file

@ -53,7 +53,13 @@ import javax.security.auth.x500.X500Principal;
within that package; the object implementing that interface is within that package; the object implementing that interface is
provided through a third package to which access is restricted. provided through a third package to which access is restricted.
This framework avoids the primary disadvantage of using reflection This framework avoids the primary disadvantage of using reflection
for this purpose, namely the loss of compile-time checking. */ for this purpose, namely the loss of compile-time checking.
* <p><strong>
* Usage of these APIs often means bad encapsulation designs,
* increased complexity and lack of sustainability.
* Use this only as a last resort!
* </strong>
*/
public class SharedSecrets { public class SharedSecrets {
private static JavaAWTAccess javaAWTAccess; private static JavaAWTAccess javaAWTAccess;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -179,41 +179,6 @@ public class ReflectionFactory {
// //
// //
/** Creates a new java.lang.reflect.Constructor. Access checks as
per java.lang.reflect.AccessibleObject are not overridden. */
public Constructor<?> newConstructor(Class<?> declaringClass,
Class<?>[] parameterTypes,
Class<?>[] checkedExceptions,
int modifiers,
int slot,
String signature,
byte[] annotations,
byte[] parameterAnnotations)
{
return langReflectAccess.newConstructor(declaringClass,
parameterTypes,
checkedExceptions,
modifiers,
slot,
signature,
annotations,
parameterAnnotations);
}
/** Gets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
return langReflectAccess.getConstructorAccessor(c);
}
/** Sets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor)
{
langReflectAccess.setConstructorAccessor(c, accessor);
}
/** Makes a copy of the passed method. The returned method is a /** Makes a copy of the passed method. The returned method is a
"child" of the passed one; see the comments in Method.java for "child" of the passed one; see the comments in Method.java for
details. */ details. */
@ -225,10 +190,10 @@ public class ReflectionFactory {
* a "child" but a "sibling" of the Method in arg. Should only be * a "child" but a "sibling" of the Method in arg. Should only be
* used on non-root methods. */ * used on non-root methods. */
public Method leafCopyMethod(Method arg) { public Method leafCopyMethod(Method arg) {
return langReflectAccess.leafCopyMethod(arg); Method root = langReflectAccess.getRoot(arg);
return langReflectAccess.copyMethod(root);
} }
/** Makes a copy of the passed field. The returned field is a /** Makes a copy of the passed field. The returned field is a
"child" of the passed one; see the comments in Field.java for "child" of the passed one; see the comments in Field.java for
details. */ details. */
@ -369,15 +334,6 @@ public class ReflectionFactory {
private final Constructor<?> generateConstructor(Class<?> cl, private final Constructor<?> generateConstructor(Class<?> cl,
Constructor<?> constructorToCall) { Constructor<?> constructorToCall) {
Constructor<?> ctor = newConstructor(constructorToCall.getDeclaringClass(),
constructorToCall.getParameterTypes(),
constructorToCall.getExceptionTypes(),
constructorToCall.getModifiers(),
langReflectAccess.getConstructorSlot(constructorToCall),
langReflectAccess.getConstructorSignature(constructorToCall),
langReflectAccess.getConstructorAnnotations(constructorToCall),
langReflectAccess.getConstructorParameterAnnotations(constructorToCall));
ConstructorAccessor acc; ConstructorAccessor acc;
if (useOldSerializableConstructor()) { if (useOldSerializableConstructor()) {
acc = new SerializationConstructorAccessorGenerator(). acc = new SerializationConstructorAccessorGenerator().
@ -386,9 +342,12 @@ public class ReflectionFactory {
constructorToCall.getModifiers(), constructorToCall.getModifiers(),
constructorToCall.getDeclaringClass()); constructorToCall.getDeclaringClass());
} else { } else {
acc = MethodHandleAccessorFactory.newSerializableConstructorAccessor(cl, ctor); acc = MethodHandleAccessorFactory.newSerializableConstructorAccessor(cl, constructorToCall);
} }
setConstructorAccessor(ctor, acc); // Unlike other root constructors, this constructor is not copied for mutation
// but directly mutated, as it is not cached. To cache this constructor,
// setAccessible call must be done on a copy and return that copy instead.
Constructor<?> ctor = langReflectAccess.newConstructorWithAccessor(constructorToCall, acc);
ctor.setAccessible(true); ctor.setAccessible(true);
return ctor; return ctor;
} }