Licensee impact of JDK 1.4 reflection changes

Sun's JDK 1.4 contains a new implementation of java.lang.reflect which offers substantially higher performance than previous JDKs' native code. Licensees can at their discretion port these changes. There are no public API or documentation changes associated with the new reflection implementation aside from a few minor clarifications in the specifications of Method.invoke(), Constructor.newInstance(), and a few methods in java.lang.reflect.Field.

The bulk of the new implementation is Java programming language code which generates bytecodes, and is therefore portable. If licensees desire to port it, the following JVM changes are required:

1. The following four new JVM entry points must be added:
   - JVM_GetClassDeclaredConstructors
   - JVM_GetClassDeclaredFields
   - JVM_GetClassDeclaredMethods
   - JVM_GetClassAccessFlags
   The first three return the declared constructors, fields, and methods for a given class, with an option to return only the public ones. They are similar in functionality to the earlier GetClassConstructors, GetClassFields, and GetClassMethods. JVM_GetClassDeclaredFields and JVM_GetClassDeclaredMethods must intern the Strings for the names of the Field and Method objects returned. The fouth returns the access flags for a given class as marked in the class file, as opposed to in the InnerClasses attribute if the class is an inner class, and therefore differs from JVM_GetClassModifiers for inner classes (most importantly, protected inner classes; see 4471811.)
2. The JVM's link resolver must be modified to allow all field and method references from subclasses of sun.reflect.MagicAccessorImpl to any other class (even to private members of other classes) to succeed. This allows setAccessible() and its associated checks to be implemented in Java.
3. The code which calls the verifier must skip verification for all subclasses of sun.reflect.MagicAccessorImpl. (It was originally intended that only a subset of the stub classes used for serialization would not pass the verifier, specifically, those subclassing SerializationConstructorAccessorImpl; see 4486457 for a case where this does not work.)
4. The stack walker for security checks must be modified to skip not only all Method.invoke() frames, but also any frames for which the class is a subclass of sun.reflect.MethodAccessorImpl.
5. The JVM entry points JVM_InvokeMethod and JVM_NewInstanceFromConstructor are currently still used because the first invocation of the bytecode-based reflection is currently slower than the original native code. The security checks they perform can, however, be disabled, as they are now performed by Java programming language code.

The following changes were discovered to be necessary for backward compatibility with certain applications (see bug 4474172):

1. The existing JVM entry point JVM_LatestUserDefinedLoader (typically used in applications which rely on the 1.1 security framework) must skip reflection-related frames in its stack walk: specifically all frames associated with subclasses of sun.reflect.MethodAccessorImpl and sun.reflect.ConstructorAccessorImpl.
2. The new reflection implementation can cause class loading to occur in previously-unexpected places (namely during reflective calls). This can cause class loaders which contain subtle bugs to break. In general it is not possible to guarantee complete backward bug compatibility, but one kind of bug has been observed more than once: the inability of a user-defined loader to handle delegation to it for a class it has already loaded. The new reflection implementation is predicated on delegation working properly, as it loads stub classes into newly-fabricated class loaders of type sun.reflect.DelegatingClassLoader, one stub class per loader, to allow unloading of the stub classes to occur more quickly. To handle this kind of bug, the JVM's internal class lookup mechanism must be slightly modified to check for instances of sun.reflect.DelegatingClassLoader as the incoming class loader and silently traverse the "parent" field once for such loaders before entering the bulk of the resolution code. This avoids an upcall to Java programming language code which certain loaders can not handle.

The following JVM entry points may be deleted:

- JVM_GetClassFields
- JVM_GetClassMethods
- JVM_GetClassConstructors
- JVM_GetClassField
- JVM_GetClassMethod
- JVM_GetClassConstructor
- JVM_NewInstance
- JVM_GetField
- JVM_GetPrimitiveField
- JVM_SetField
- JVM_SetPrimitiveField

To keep using the previous reflection implementation, licensees should not take changes from Sun's JDK 1.4 relating specifically to the implementation of reflection in the following classes/methods and any associated native code:

- java.lang.Class.newInstance0
- java.lang.Class.getClassLoader0
- java.lang.Class.getFields
- java.lang.Class.getMethods
- java.lang.Class.getDeclaredFields
- java.lang.Class.getDeclaredMethods
- java.lang.Class.getFields0
- java.lang.Class.getMethods0
- java.lang.Class.getConstructors0
- java.lang.Class.getField0
- java.lang.Class.getMethod0
- java.lang.Class.getConstructor0
- java.lang.ClassLoader.getCallerClassLoader
- java.lang.System.getCallerClass
- java.lang.reflect.AccessibleObject
- java.lang.reflect.Constructor
- java.lang.reflect.Field
- java.lang.reflect.Method
- java.lang.reflect.Modifier
- sun.misc.ClassReflector