< prev index next >

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

Print this page
@@ -30,22 +30,26 @@
  import java.lang.constant.MethodTypeDesc;
  import java.lang.ref.Reference;
  import java.lang.ref.ReferenceQueue;
  import java.lang.ref.WeakReference;
  import java.util.Arrays;
+ import java.util.ArrayList;
  import java.util.Collections;
  import java.util.function.Supplier;
+ import java.util.HashMap;
+ import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Objects;
  import java.util.Optional;
  import java.util.StringJoiner;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
  import java.util.stream.Stream;
  
+ import jdk.internal.misc.CDS;
  import jdk.internal.util.ReferencedKeySet;
  import jdk.internal.util.ReferenceKey;
  import jdk.internal.vm.annotation.Stable;
  import sun.invoke.util.BytecodeDescriptor;
  import sun.invoke.util.VerifyType;

@@ -152,15 +156,23 @@
      private @Stable Object wrapAlt;  // alternative wrapped/unwrapped version and
                                       // private communication for readObject and readResolve
      private @Stable Invokers invokers;   // cache of handy higher-order adapters
      private @Stable String methodDescriptor;  // cache for toMethodDescriptorString
  
+     private final boolean checkArchivable = CDS.isDumpingArchive();
      /**
       * Constructor that performs no copying or validation.
       * Should only be called from the factory method makeImpl
       */
      private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+         if (checkArchivable) {
+             MethodHandleNatives.checkArchivable(rtype);
+             for (var p : ptypes) {
+                 MethodHandleNatives.checkArchivable(p);
+             }
+         }
+ 
          this.rtype = rtype;
          this.ptypes = ptypes;
      }
  
      /*trusted*/ MethodTypeForm form() { return form; }

@@ -238,10 +250,30 @@
              }
          });
  
      static final Class<?>[] NO_PTYPES = {};
  
+     private static Object[] archivedObjects;
+ 
+     private static @Stable HashMap<MethodType,MethodType> archivedMethodTypes;
+ 
+     private static @Stable MethodType[] objectOnlyTypes;
+ 
+     @SuppressWarnings("unchecked")
+     static void doit() {
+         CDS.initializeFromArchive(MethodType.class);
+         if (archivedObjects != null) {
+             archivedMethodTypes = (HashMap<MethodType,MethodType>)archivedObjects[0];
+             objectOnlyTypes = (MethodType[])archivedObjects[1];
+         } else {
+             objectOnlyTypes = new MethodType[20];
+         }
+     }
+     static {
+         doit();
+     }
+ 
      /**
       * Finds or creates an instance of the given method type.
       * @param rtype  the return type
       * @param ptypes the parameter types
       * @return a method type with the given components

@@ -396,10 +428,17 @@
      private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
          if (ptypes.length == 0) {
              ptypes = NO_PTYPES; trusted = true;
          }
          MethodType primordialMT = new MethodType(rtype, ptypes);
+         if (archivedMethodTypes != null) {
+             MethodType mt = archivedMethodTypes.get(primordialMT);
+             if (mt != null) {
+                 return mt;
+             }
+         }
+ 
          MethodType mt = internTable.get(primordialMT);
          if (mt != null)
              return mt;
  
          // promote the object to the Real Thing, and reprobe

@@ -414,11 +453,10 @@
              mt = new MethodType(rtype, ptypes);
          }
          mt.form = MethodTypeForm.findForm(mt);
          return internTable.intern(mt);
      }
-     private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
  
      /**
       * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
       * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
       * All parameters and the return type will be {@code Object},

@@ -1389,6 +1427,56 @@
          // Return a new validated MethodType for the rtype and ptypes passed from readObject.
          MethodType mt = ((MethodType[])wrapAlt)[0];
          wrapAlt = null;
          return mt;
      }
+ 
+     static HashMap<MethodType,MethodType> archive(Archiver archiver) {
+         HashMap<MethodType,MethodType> archivedSet = new HashMap<>();
+ 
+         for (Iterator<MethodType> i = internTable.iterator(); i.hasNext(); ) {
+             MethodType t = i.next();
+             MethodType a = archiver.clean(t);
+             if (a != null) {
+                 archivedSet.put(a, a);
+             }
+         }
+ 
+         return archivedSet;
+     }
+ 
+     static class Archiver {
+         ArrayList<MethodType> archived = new ArrayList<>();
+ 
+         MethodType clean(MethodType t) {
+             if (t == null || t.form == null) { // HACK!
+                 return null;
+             }
+             if (archived.contains(t)) {
+                 return t;
+             }
+ 
+             archived.add(t);
+             return t;
+         }
+     }
+ 
+     // This is called from C code.
+     static void dumpSharedArchive() {
+         Archiver archiver = new Archiver();
+ 
+         MethodType[] objectOnlyTypesCopy = new MethodType[objectOnlyTypes.length];
+         for (int i = 0; i < objectOnlyTypes.length; i++) {
+             MethodType t = archiver.clean(objectOnlyTypes[i]);
+             if (t != null) {
+                 objectOnlyTypesCopy[i] = t;
+             }
+         }
+ 
+         archivedObjects = new Object[2];
+         archivedObjects[0] = archive(archiver);
+         archivedObjects[1] = objectOnlyTypesCopy;
+ 
+         DirectMethodHandle.dumpSharedArchive();
+         LambdaForm.NamedFunction.dumpSharedArchive();
+     }
  }
< prev index next >