src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java
changeset 59201 b24f4caa1411
parent 51319 3142a04a2f6d
equal deleted inserted replaced
59200:a686b67a59d9 59201:b24f4caa1411
   150     // private constructors, or interfaces with multiple but related
   150     // private constructors, or interfaces with multiple but related
   151     // entry points, must be covered by hand-written or automatically
   151     // entry points, must be covered by hand-written or automatically
   152     // generated adapter classes.
   152     // generated adapter classes.
   153     //
   153     //
   154     @CallerSensitive
   154     @CallerSensitive
   155     public static
   155     public static <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
   156     <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
       
   157         if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
   156         if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
   158             throw newIllegalArgumentException("not a public interface", intfc.getName());
   157             throw newIllegalArgumentException("not a public interface", intfc.getName());
   159         final MethodHandle mh;
   158         final MethodHandle mh;
   160         if (System.getSecurityManager() != null) {
   159         if (System.getSecurityManager() != null) {
   161             final Class<?> caller = Reflection.getCallerClass();
   160             final Class<?> caller = Reflection.getCallerClass();
   233     /**
   232     /**
   234      * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
   233      * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
   235      * @param x any reference
   234      * @param x any reference
   236      * @return true if the reference is not null and points to an object produced by {@code asInterfaceInstance}
   235      * @return true if the reference is not null and points to an object produced by {@code asInterfaceInstance}
   237      */
   236      */
   238     public static
   237     public static boolean isWrapperInstance(Object x) {
   239     boolean isWrapperInstance(Object x) {
       
   240         return x instanceof WrapperInstance;
   238         return x instanceof WrapperInstance;
   241     }
   239     }
   242 
   240 
   243     private static WrapperInstance asWrapperInstance(Object x) {
   241     private static WrapperInstance asWrapperInstance(Object x) {
   244         try {
   242         try {
   256      * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
   254      * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
   257      * @param x any reference
   255      * @param x any reference
   258      * @return a method handle implementing the unique method
   256      * @return a method handle implementing the unique method
   259      * @throws IllegalArgumentException if the reference x is not to a wrapper instance
   257      * @throws IllegalArgumentException if the reference x is not to a wrapper instance
   260      */
   258      */
   261     public static
   259     public static MethodHandle wrapperInstanceTarget(Object x) {
   262     MethodHandle wrapperInstanceTarget(Object x) {
       
   263         return asWrapperInstance(x).getWrapperInstanceTarget();
   260         return asWrapperInstance(x).getWrapperInstanceTarget();
   264     }
   261     }
   265 
   262 
   266     /**
   263     /**
   267      * Recovers the unique single-method interface type for which this wrapper instance was created.
   264      * Recovers the unique single-method interface type for which this wrapper instance was created.
   269      * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
   266      * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
   270      * @param x any reference
   267      * @param x any reference
   271      * @return the single-method interface type for which the wrapper was created
   268      * @return the single-method interface type for which the wrapper was created
   272      * @throws IllegalArgumentException if the reference x is not to a wrapper instance
   269      * @throws IllegalArgumentException if the reference x is not to a wrapper instance
   273      */
   270      */
   274     public static
   271     public static Class<?> wrapperInstanceType(Object x) {
   275     Class<?> wrapperInstanceType(Object x) {
       
   276         return asWrapperInstance(x).getWrapperInstanceType();
   272         return asWrapperInstance(x).getWrapperInstanceType();
   277     }
   273     }
   278 
   274 
   279     private static
   275     private static boolean isObjectMethod(Method m) {
   280     boolean isObjectMethod(Method m) {
       
   281         switch (m.getName()) {
   276         switch (m.getName()) {
   282         case "toString":
   277         case "toString":
   283             return (m.getReturnType() == String.class
   278             return (m.getReturnType() == String.class
   284                     && m.getParameterTypes().length == 0);
   279                     && m.getParameterTypes().length == 0);
   285         case "hashCode":
   280         case "hashCode":
   291                     && m.getParameterTypes()[0] == Object.class);
   286                     && m.getParameterTypes()[0] == Object.class);
   292         }
   287         }
   293         return false;
   288         return false;
   294     }
   289     }
   295 
   290 
   296     private static
   291     private static Object callObjectMethod(Object self, Method m, Object[] args) {
   297     Object callObjectMethod(Object self, Method m, Object[] args) {
       
   298         assert(isObjectMethod(m)) : m;
   292         assert(isObjectMethod(m)) : m;
   299         switch (m.getName()) {
   293         switch (m.getName()) {
   300         case "toString":
   294         case "toString":
   301             return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
   295             return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
   302         case "hashCode":
   296         case "hashCode":
   305             return (self == args[0]);
   299             return (self == args[0]);
   306         }
   300         }
   307         return null;
   301         return null;
   308     }
   302     }
   309 
   303 
   310     private static
   304     private static Method[] getSingleNameMethods(Class<?> intfc) {
   311     Method[] getSingleNameMethods(Class<?> intfc) {
       
   312         ArrayList<Method> methods = new ArrayList<>();
   305         ArrayList<Method> methods = new ArrayList<>();
   313         String uniqueName = null;
   306         String uniqueName = null;
   314         for (Method m : intfc.getMethods()) {
   307         for (Method m : intfc.getMethods()) {
   315             if (isObjectMethod(m))  continue;
   308             if (isObjectMethod(m))  continue;
   316             if (!Modifier.isAbstract(m.getModifiers()))  continue;
   309             if (!Modifier.isAbstract(m.getModifiers()))  continue;
   323         }
   316         }
   324         if (uniqueName == null)  return null;
   317         if (uniqueName == null)  return null;
   325         return methods.toArray(new Method[methods.size()]);
   318         return methods.toArray(new Method[methods.size()]);
   326     }
   319     }
   327 
   320 
   328     private static
   321     private static boolean isDefaultMethod(Method m) {
   329     boolean isDefaultMethod(Method m) {
       
   330         return !Modifier.isAbstract(m.getModifiers());
   322         return !Modifier.isAbstract(m.getModifiers());
   331     }
   323     }
   332 
   324 
   333     private static
   325     private static boolean hasDefaultMethods(Class<?> intfc) {
   334     boolean hasDefaultMethods(Class<?> intfc) {
       
   335         for (Method m : intfc.getMethods()) {
   326         for (Method m : intfc.getMethods()) {
   336             if (!isObjectMethod(m) &&
   327             if (!isObjectMethod(m) &&
   337                 !Modifier.isAbstract(m.getModifiers())) {
   328                 !Modifier.isAbstract(m.getModifiers())) {
   338                 return true;
   329                 return true;
   339             }
   330             }
   340         }
   331         }
   341         return false;
   332         return false;
   342     }
   333     }
   343 
   334 
   344     private static
   335     private static Object callDefaultMethod(ConcurrentHashMap<Method, MethodHandle> defaultMethodMap,
   345     Object callDefaultMethod(ConcurrentHashMap<Method, MethodHandle> defaultMethodMap,
       
   346                              Object self, Class<?> intfc, Method m, Object[] args) throws Throwable {
   336                              Object self, Class<?> intfc, Method m, Object[] args) throws Throwable {
   347         assert(isDefaultMethod(m) && !isObjectMethod(m)) : m;
   337         assert(isDefaultMethod(m) && !isObjectMethod(m)) : m;
   348 
   338 
   349         // Lazily compute the associated method handle from the method
   339         // Lazily compute the associated method handle from the method
   350         MethodHandle dmh = defaultMethodMap.computeIfAbsent(m, mk -> {
   340         MethodHandle dmh = defaultMethodMap.computeIfAbsent(m, mk -> {