diff a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
--- a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
@@ -28,10 +28,11 @@
 import sun.invoke.util.Wrapper;
 
 import java.lang.ref.SoftReference;
 
 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+import static java.lang.invoke.MethodHandleStatics.NO_SOFT_CACHE;
 
 /**
  * Shared information for a group of method types, which differ
  * only by reference types, and therefore share a common erasure
  * and wrapping.
@@ -49,21 +50,21 @@
     final short primitiveCount;
     final MethodType erasedType;        // the canonical erasure
     final MethodType basicType;         // the canonical erasure, with primitives simplified
 
     // Cached adapter information:
-    final SoftReference<MethodHandle>[] methodHandles;
+    private final Object[] methodHandles;
 
     // Indexes into methodHandles:
     static final int
             MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
             MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
             MH_UNINIT_CS      =  2,  // uninitialized call site
             MH_LIMIT          =  3;
 
     // Cached lambda form information, for basic types only:
-    final SoftReference<LambdaForm>[] lambdaForms;
+    private final Object[] lambdaForms;
 
     // Indexes into lambdaForms:
     static final int
             LF_INVVIRTUAL              =  0,  // DMH invokeVirtual
             LF_INVSTATIC               =  1,
@@ -107,43 +108,59 @@
      */
     public MethodType basicType() {
         return basicType;
     }
 
+    @SuppressWarnings({"rawtypes", "unchecked"})
     public MethodHandle cachedMethodHandle(int which) {
-        SoftReference<MethodHandle> entry = methodHandles[which];
-        return (entry != null) ? entry.get() : null;
+        Object entry = methodHandles[which];
+        if (entry == null) {
+            return null;
+        } else if (entry instanceof MethodHandle) {
+            return (MethodHandle) entry;
+        } else {
+            return ((SoftReference<MethodHandle>)entry).get();
+        }
     }
 
     public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
         // Simulate a CAS, to avoid racy duplication of results.
-        SoftReference<MethodHandle> entry = methodHandles[which];
-        if (entry != null) {
-            MethodHandle prev = entry.get();
-            if (prev != null) {
-                return prev;
-            }
+        MethodHandle prev = cachedMethodHandle(which);
+        if (prev != null) {
+            return prev;
+        }
+        if (NO_SOFT_CACHE) {
+            methodHandles[which] = mh;
+        } else {
+            methodHandles[which] = new SoftReference<>(mh);
         }
-        methodHandles[which] = new SoftReference<>(mh);
         return mh;
     }
 
+    @SuppressWarnings({"rawtypes", "unchecked"})
     public LambdaForm cachedLambdaForm(int which) {
-        SoftReference<LambdaForm> entry = lambdaForms[which];
-        return (entry != null) ? entry.get() : null;
+        Object entry = lambdaForms[which];
+        if (entry == null) {
+            return null;
+        } else if (entry instanceof LambdaForm) {
+            return (LambdaForm) entry;
+        } else {
+            return ((SoftReference<LambdaForm>)entry).get();
+        }
     }
 
     public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
         // Simulate a CAS, to avoid racy duplication of results.
-        SoftReference<LambdaForm> entry = lambdaForms[which];
-        if (entry != null) {
-            LambdaForm prev = entry.get();
-            if (prev != null) {
-                return prev;
-            }
+        LambdaForm prev = cachedLambdaForm(which);
+        if (prev != null) {
+            return prev;
+        }
+        if (NO_SOFT_CACHE) {
+            lambdaForms[which] = form;
+        } else {
+            lambdaForms[which] = new SoftReference<>(form);
         }
-        lambdaForms[which] = new SoftReference<>(form);
         return form;
     }
 
     /**
      * Build an MTF for a given type, which must have all references erased to Object.
@@ -189,12 +206,12 @@
 
             if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 
             this.primitiveCount = primitiveCount;
             this.parameterSlotCount = (short)pslotCount;
-            this.lambdaForms   = new SoftReference[LF_LIMIT];
-            this.methodHandles = new SoftReference[MH_LIMIT];
+            this.lambdaForms   = new Object[LF_LIMIT];
+            this.methodHandles = new Object[MH_LIMIT];
         } else {
             this.basicType = MethodType.methodType(basicReturnType, basicPtypes, true);
             // fill in rest of data from the basic type:
             MethodTypeForm that = this.basicType.form();
             assert(this != that);
