diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java index efc47edece4d..25e48044eb7d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java @@ -35,7 +35,9 @@ import java.util.Iterator; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import com.oracle.svm.core.jdk.JDK21u4OrLater; import org.graalvm.nativeimage.hosted.RuntimeReflection; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; @@ -101,7 +103,7 @@ public class MethodHandleFeature implements InternalFeature { * equivalent image heap object is not part of the table and subsequently fails a comparison. */ private Object runtimeMethodTypeInternTable; - private Method concurrentWeakInternSetAdd; + private Method referencedKeySetAdd; private MethodHandleInvokerRenamingSubstitutionProcessor substitutionProcessor; @@ -122,9 +124,22 @@ public void duringSetup(DuringSetupAccess access) { Class arrayAccessorClass = access.findClassByName("java.lang.invoke.MethodHandleImpl$ArrayAccessor"); typedAccessors = ReflectionUtil.lookupField(arrayAccessorClass, "TYPED_ACCESSORS"); - Class concurrentWeakInternSetClass = access.findClassByName("java.lang.invoke.MethodType$ConcurrentWeakInternSet"); - runtimeMethodTypeInternTable = ReflectionUtil.newInstance(concurrentWeakInternSetClass); - concurrentWeakInternSetAdd = ReflectionUtil.lookupMethod(concurrentWeakInternSetClass, "add", Object.class); + if (JDK21u4OrLater.jdk21u4OrLater) { + try { + Class referencedKeySetClass = access.findClassByName("jdk.internal.util.ReferencedKeySet"); + Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class); + // The following call must match the static initializer of MethodType#internTable. + runtimeMethodTypeInternTable = create.invoke(null, + /* isSoft */ false, /* useNativeQueue */ true, (Supplier) () -> new ConcurrentHashMap<>(512)); + referencedKeySetAdd = ReflectionUtil.lookupMethod(referencedKeySetClass, "add", Object.class); + } catch (ReflectiveOperationException e) { + throw VMError.shouldNotReachHere(e); + } + } else { + Class concurrentWeakInternSetClass = access.findClassByName("java.lang.invoke.MethodType$ConcurrentWeakInternSet"); + runtimeMethodTypeInternTable = ReflectionUtil.newInstance(concurrentWeakInternSetClass); + referencedKeySetAdd = ReflectionUtil.lookupMethod(concurrentWeakInternSetClass, "add", Object.class); + } if (!SubstrateOptions.UseOldMethodHandleIntrinsics.getValue()) { /* @@ -322,7 +337,7 @@ private static void registerVarHandleMethodsForReflection(FeatureAccess access, public void registerHeapMethodType(MethodType methodType) { try { - concurrentWeakInternSetAdd.invoke(runtimeMethodTypeInternTable, methodType); + referencedKeySetAdd.invoke(runtimeMethodTypeInternTable, methodType); } catch (ReflectiveOperationException e) { throw VMError.shouldNotReachHere(e); }