diff a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java
@@ -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();
+    }
 }
