< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandle.java

Print this page

        

@@ -24,10 +24,11 @@
  */
 
 package java.lang.invoke;
 
 
+import java.lang.ref.WeakReference;
 import java.util.*;
 
 import static java.lang.invoke.MethodHandleStatics.*;
 
 /**

@@ -430,12 +431,11 @@
     @interface PolymorphicSignature { }
 
     private final MethodType type;
     /*private*/ final LambdaForm form;
     // form is not private so that invokers can easily fetch it
-    /*private*/ MethodHandle asTypeCache;
-    // asTypeCache is not private so that invokers can easily fetch it
+    private WeakReference<MethodHandle> asTypeCache;
     /*non-public*/ byte customizationCount;
     // customizationCount should be accessible from invokers
 
     /**
      * Reports the type of this method handle.

@@ -743,37 +743,40 @@
      *           necessary return value conversions
      * @throws NullPointerException if {@code newType} is a null reference
      * @throws WrongMethodTypeException if the conversion cannot be made
      * @see MethodHandles#explicitCastArguments
      */
-    public MethodHandle asType(MethodType newType) {
+    public final MethodHandle asType(MethodType newType) {
         // Fast path alternative to a heavyweight {@code asType} call.
         // Return 'this' if the conversion will be a no-op.
         if (newType == type) {
             return this;
         }
         // Return 'this.asTypeCache' if the conversion is already memoized.
-        MethodHandle atc = asTypeCached(newType);
-        if (atc != null) {
-            return atc;
+        MethodHandle at = asTypeCached(newType);
+        if (at != null) {
+            return at;
         }
-        return asTypeUncached(newType);
+        at = asTypeUncached(newType);
+        asTypeCache = new WeakReference<>(at);
+        return at;
     }
 
     private MethodHandle asTypeCached(MethodType newType) {
-        MethodHandle atc = asTypeCache;
-        if (atc != null && newType == atc.type) {
+        MethodHandle atc;
+        if (asTypeCache != null && (atc = asTypeCache.get()) != null &&
+                newType == atc.type) {
             return atc;
         }
         return null;
     }
 
     /** Override this to change asType behavior. */
     /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
         if (!type.isConvertibleTo(newType))
             throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
-        return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true);
+        return MethodHandleImpl.makePairwiseConvert(this, newType, true);
     }
 
     /**
      * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
      * and spreads its elements as positional arguments.
< prev index next >