< prev index next >

src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java

Print this page
*** 83,10 ***
--- 83,19 ---
      // Package-private to be accessible to NativeMethodAccessorImpl
      // and NativeConstructorAccessorImpl
      private static boolean noInflation        = false;
      private static int     inflationThreshold = 15;
  
+     //
+     // New implementation uses direct invocation of method handles
+     private static final int METHOD_MH_ACCESSOR      = 0x1;
+     private static final int FIELD_MH_ACCESSOR       = 0x2;
+     private static final int ALL_MH_ACCESSORS        = METHOD_MH_ACCESSOR|FIELD_MH_ACCESSOR;
+ 
+     private static int     useDirectMethodHandle = ALL_MH_ACCESSORS;
+     private static boolean useNativeAccessorOnly = false;  // for testing only
+ 
      // true if deserialization constructor checking is disabled
      private static boolean disableSerialConstructorChecks = false;
  
      private final JavaLangReflectAccess langReflectAccess;
      private ReflectionFactory() {

*** 135,28 ***
                  SecurityConstants.REFLECTION_FACTORY_ACCESS_PERMISSION);
          }
          return soleInstance;
      }
  
-     /**
-      * Returns an alternate reflective Method instance for the given method
-      * intended for reflection to invoke, if present.
-      *
-      * A trusted method can define an alternate implementation for a method `foo`
-      * by defining a method named "reflected$foo" that will be invoked
-      * reflectively.
-      */
-     private static Method findMethodForReflection(Method method) {
-         String altName = "reflected$" + method.getName();
-         try {
-            return method.getDeclaringClass()
-                         .getDeclaredMethod(altName, method.getParameterTypes());
-         } catch (NoSuchMethodException ex) {
-             return null;
-         }
-     }
- 
      //--------------------------------------------------------------------------
      //
      // Routines used by java.lang.reflect
      //
      //
--- 144,10 ---

*** 179,43 ***
                  field = root;
              }
          }
          boolean isFinal = Modifier.isFinal(field.getModifiers());
          boolean isReadOnly = isFinal && (!override || langReflectAccess.isTrustedFinalField(field));
!         return UnsafeFieldAccessorFactory.newFieldAccessor(field, isReadOnly);
      }
  
!     public MethodAccessor newMethodAccessor(Method method) {
          checkInitted();
  
-         if (Reflection.isCallerSensitive(method)) {
-             Method altMethod = findMethodForReflection(method);
-             if (altMethod != null) {
-                 method = altMethod;
-             }
-         }
- 
          // use the root Method that will not cache caller class
          Method root = langReflectAccess.getRoot(method);
          if (root != null) {
              method = root;
          }
  
!         if (noInflation && !method.getDeclaringClass().isHidden()) {
!             return new MethodAccessorGenerator().
-                 generateMethod(method.getDeclaringClass(),
-                                method.getName(),
-                                method.getParameterTypes(),
-                                method.getReturnType(),
-                                method.getExceptionTypes(),
-                                method.getModifiers());
          } else {
!             NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method);
!             return acc.getParent();
          }
      }
  
      public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
          checkInitted();
  
          Class<?> declaringClass = c.getDeclaringClass();
          if (Modifier.isAbstract(declaringClass.getModifiers())) {
--- 170,52 ---
                  field = root;
              }
          }
          boolean isFinal = Modifier.isFinal(field.getModifiers());
          boolean isReadOnly = isFinal && (!override || langReflectAccess.isTrustedFinalField(field));
!         if (useFieldHandleAccessor()) {
+             return MethodHandleAccessorFactory.newFieldAccessor(field, isReadOnly);
+         } else {
+             return UnsafeFieldAccessorFactory.newFieldAccessor(field, isReadOnly);
+         }
      }
  
!     public MethodAccessor newMethodAccessor(Method method, boolean callerSensitive) {
          checkInitted();
  
          // use the root Method that will not cache caller class
          Method root = langReflectAccess.getRoot(method);
          if (root != null) {
              method = root;
          }
  
!         if (useMethodHandleAccessor()) {
!             return MethodHandleAccessorFactory.newMethodAccessor(method, callerSensitive);
          } else {
!             if (noInflation && !method.getDeclaringClass().isHidden()) {
!                 return generateMethodAccessor(method);
+             } else {
+                 NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method);
+                 return acc.getParent();
+             }
          }
      }
  
+     /**
+      * Generate the MethodAccessor that invokes the given method with
+      * bytecode invocation.
+      */
+     static MethodAccessorImpl generateMethodAccessor(Method method) {
+         return (MethodAccessorImpl)new MethodAccessorGenerator()
+                 .generateMethod(method.getDeclaringClass(),
+                                 method.getName(),
+                                 method.getParameterTypes(),
+                                 method.getReturnType(),
+                                 method.getExceptionTypes(),
+                                 method.getModifiers());
+     }
+ 
      public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
          checkInitted();
  
          Class<?> declaringClass = c.getDeclaringClass();
          if (Modifier.isAbstract(declaringClass.getModifiers())) {

*** 230,27 ***
          Constructor<?> root = langReflectAccess.getRoot(c);
          if (root != null) {
              c = root;
          }
  
!         // Bootstrapping issue: since we use Class.newInstance() in
!         // the ConstructorAccessor generation process, we have to
-         // break the cycle here.
-         if (Reflection.isSubclassOf(declaringClass,
-                                     ConstructorAccessorImpl.class)) {
-             return new BootstrapConstructorAccessorImpl(c);
-         }
- 
-         if (noInflation && !c.getDeclaringClass().isHidden()) {
-             return new MethodAccessorGenerator().
-                 generateConstructor(c.getDeclaringClass(),
-                                     c.getParameterTypes(),
-                                     c.getExceptionTypes(),
-                                     c.getModifiers());
          } else {
!             NativeConstructorAccessorImpl acc = new NativeConstructorAccessorImpl(c);
!             return acc.getParent();
          }
      }
  
      //--------------------------------------------------------------------------
      //
--- 230,30 ---
          Constructor<?> root = langReflectAccess.getRoot(c);
          if (root != null) {
              c = root;
          }
  
!         if (useMethodHandleAccessor()) {
!             return MethodHandleAccessorFactory.newConstructorAccessor(c);
          } else {
!             // Bootstrapping issue: since we use Class.newInstance() in
!             // the ConstructorAccessor generation process, we have to
+             // break the cycle here.
+             if (Reflection.isSubclassOf(declaringClass, ConstructorAccessorImpl.class)) {
+                 return new BootstrapConstructorAccessorImpl(c);
+             }
+ 
+             if (noInflation && !c.getDeclaringClass().isHidden()) {
+                 return new MethodAccessorGenerator().
+                         generateConstructor(c.getDeclaringClass(),
+                                             c.getParameterTypes(),
+                                             c.getExceptionTypes(),
+                                             c.getModifiers());
+             } else {
+                 NativeConstructorAccessorImpl acc = new NativeConstructorAccessorImpl(c);
+                 return acc.getParent();
+             }
          }
      }
  
      //--------------------------------------------------------------------------
      //

*** 621,10 ***
--- 624,26 ---
  
      static int inflationThreshold() {
          return inflationThreshold;
      }
  
+     static boolean noInflation() {
+         return noInflation;
+     }
+ 
+     static boolean useMethodHandleAccessor() {
+         return (useDirectMethodHandle & METHOD_MH_ACCESSOR) == METHOD_MH_ACCESSOR;
+     }
+ 
+     static boolean useFieldHandleAccessor() {
+         return (useDirectMethodHandle & FIELD_MH_ACCESSOR) == FIELD_MH_ACCESSOR;
+     }
+ 
+     static boolean useNativeAccessorOnly() {
+         return useNativeAccessorOnly;
+     }
+ 
      /** We have to defer full initialization of this class until after
          the static initializer is run since java.lang.reflect.Method's
          static initializer (more properly, that for
          java.lang.reflect.AccessibleObject) causes this class's to be
          run, before the system properties are set up. */

*** 650,10 ***
--- 669,24 ---
                  inflationThreshold = Integer.parseInt(val);
              } catch (NumberFormatException e) {
                  throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
              }
          }
+         val = props.getProperty("jdk.reflect.useDirectMethodHandle");
+         if (val != null) {
+             if (val.equals("false")) {
+                 useDirectMethodHandle = 0;
+             } else if (val.equals("methods")) {
+                 useDirectMethodHandle = METHOD_MH_ACCESSOR;
+             } else if (val.equals("fields")) {
+                 useDirectMethodHandle = FIELD_MH_ACCESSOR;
+             }
+         }
+         val = props.getProperty("jdk.reflect.useNativeAccessorOnly");
+         if (val != null && val.equals("true")) {
+             useNativeAccessorOnly = true;
+         }
  
          disableSerialConstructorChecks =
              "true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));
  
          initted = true;
< prev index next >