src/share/classes/java/lang/invoke/MethodType.java

Print this page
rev 8095 : JDK-8024635 v2
rev 8096 : JDK-8024635 v2
rev 8097 : JDK-8024635 v3

@@ -30,10 +30,11 @@
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentHashMap;
 import sun.invoke.util.BytecodeDescriptor;
 import static java.lang.invoke.MethodHandleStatics.*;
 import sun.invoke.util.VerifyType;

@@ -95,18 +96,28 @@
 
     // The remaining fields are caches of various sorts:
     private MethodTypeForm form; // erased form, plus cached data about primitives
     private MethodType wrapAlt;  // alternative wrapped/unwrapped version
     private Invokers invokers;   // cache of handy higher-order adapters
+    private String methodDescriptor;
 
     /**
      * Check the given parameters for validity and store them into the final fields.
      */
-    private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+    private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
         checkRtype(rtype);
         checkPtypes(ptypes);
         this.rtype = rtype;
+        // defensively copy the array passed in by the user
+        this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
+    }
+
+    /**
+     * Don't check the given parameters for validity - creates MethodType for usage as searching key only.
+     */
+    private MethodType(Class<?>[] ptypes, Class<?> rtype) {
+        this.rtype = rtype;
         this.ptypes = ptypes;
     }
 
     /*trusted*/ MethodTypeForm form() { return form; }
     /*trusted*/ Class<?> rtype() { return rtype; }

@@ -143,24 +154,25 @@
      *  {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
      */
     /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1;  // deduct one more for invoker
 
     private static void checkRtype(Class<?> rtype) {
-        rtype.equals(rtype);  // null check
+        Objects.requireNonNull(rtype);
     }
-    private static int checkPtype(Class<?> ptype) {
-        ptype.getClass();  //NPE
+    private static void checkPtype(Class<?> ptype) {
+        Objects.requireNonNull(ptype);
         if (ptype == void.class)
             throw newIllegalArgumentException("parameter type cannot be void");
-        if (ptype == double.class || ptype == long.class)  return 1;
-        return 0;
     }
     /** Return number of extra slots (count of long/double args). */
     private static int checkPtypes(Class<?>[] ptypes) {
         int slots = 0;
         for (Class<?> ptype : ptypes) {
-            slots += checkPtype(ptype);
+            checkPtype(ptype);
+            if (ptype == double.class || ptype == long.class) {
+                slots++;
+            }
         }
         checkSlotCount(ptypes.length + slots);
         return slots;
     }
     static void checkSlotCount(int count) {

@@ -281,24 +293,20 @@
      * @param trusted whether the ptypes can be used without cloning
      * @return the unique method type of the desired structure
      */
     /*trusted*/ static
     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
+        MethodType mt = internTable.get(new MethodType(ptypes, rtype));
+        if (mt != null)
+            return mt;
         if (ptypes.length == 0) {
             ptypes = NO_PTYPES; trusted = true;
         }
-        MethodType mt1 = new MethodType(rtype, ptypes);
-        MethodType mt0 = internTable.get(mt1);
-        if (mt0 != null)
-            return mt0;
-        if (!trusted)
-            // defensively copy the array passed in by the user
-            mt1 = new MethodType(rtype, ptypes.clone());
+        mt = new MethodType(rtype, ptypes, trusted);
         // promote the object to the Real Thing, and reprobe
-        MethodTypeForm form = MethodTypeForm.findForm(mt1);
-        mt1.form = form;
-        return internTable.add(mt1);
+        mt.form = MethodTypeForm.findForm(mt);
+        return internTable.add(mt);
     }
     private static final MethodType[] objectOnlyTypes = new MethodType[20];
 
     /**
      * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.

@@ -916,11 +924,16 @@
      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
      * because the latter requires a suitable class loader argument.
      * @return the bytecode type descriptor representation
      */
     public String toMethodDescriptorString() {
-        return BytecodeDescriptor.unparse(this);
+        String desc = methodDescriptor;
+        if (desc == null) {
+            desc = BytecodeDescriptor.unparse(this);
+            methodDescriptor = desc;
+        }
+        return desc;
     }
 
     /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
         return BytecodeDescriptor.unparse(cls);
     }