diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u3OrEarlier.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u3OrEarlier.java new file mode 100644 index 00000000000..9c8a0124255 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u3OrEarlier.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.jdk; + +import java.util.function.BooleanSupplier; + +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; + +public class JDK21u3OrEarlier implements BooleanSupplier { + + public static final boolean jdk21u3OrEarlier = JavaVersionUtil.JAVA_SPEC < 21 || + (JavaVersionUtil.JAVA_SPEC == 21 && Runtime.version().update() <= 3); + + @Override + public boolean getAsBoolean() { + return jdk21u3OrEarlier; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u4OrLater.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u4OrLater.java new file mode 100644 index 00000000000..c39b8758dc1 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JDK21u4OrLater.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.jdk; + +import java.util.function.BooleanSupplier; + +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; + +public class JDK21u4OrLater implements BooleanSupplier { + + public static final boolean jdk21u4OrLater = JavaVersionUtil.JAVA_SPEC > 21 || + (JavaVersionUtil.JAVA_SPEC == 21 && Runtime.version().update() >= 4); + + @Override + public boolean getAsBoolean() { + return jdk21u4OrLater; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java index 9d9935dd0be..6fe180ddb54 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java @@ -43,6 +43,8 @@ import com.oracle.svm.core.jdk.JDK20OrEarlier; import com.oracle.svm.core.jdk.JDK20OrLater; import com.oracle.svm.core.jdk.JDK21OrLater; +import com.oracle.svm.core.jdk.JDK21u3OrEarlier; +import com.oracle.svm.core.jdk.JDK21u4OrLater; import com.oracle.svm.core.jdk.LoomJDK; import com.oracle.svm.core.jfr.HasJfrSupport; import com.oracle.svm.core.jfr.SubstrateJVM; @@ -55,15 +57,20 @@ public final class Target_java_lang_VirtualThread { // Checkstyle: stop @Alias static int NEW; @Alias static int STARTED; - @Alias static int RUNNABLE; + @Alias // + @TargetElement(onlyWith = JDK21u3OrEarlier.class) static int RUNNABLE; @Alias static int RUNNING; @Alias static int PARKING; @Alias static int PARKED; @Alias static int PINNED; @Alias static int YIELDING; + @TargetElement(onlyWith = JDK21u4OrLater.class) @Alias static int YIELDED; @Alias static int TERMINATED; - @Alias static int RUNNABLE_SUSPENDED; - @Alias static int PARKED_SUSPENDED; + @Alias static int SUSPENDED; + @TargetElement(onlyWith = JDK21u4OrLater.class) @Alias static int TIMED_PARKING; + @TargetElement(onlyWith = JDK21u4OrLater.class) @Alias static int TIMED_PARKED; + @TargetElement(onlyWith = JDK21u4OrLater.class) @Alias static int TIMED_PINNED; + @TargetElement(onlyWith = JDK21u4OrLater.class) @Alias static int UNPARKED; @Alias static Target_jdk_internal_vm_ContinuationScope VTHREAD_SCOPE; // Checkstyle: resume @@ -155,7 +162,7 @@ void unmount() { @Substitute Thread.State threadState() { - int state = state(); + int state = state() & ~SUSPENDED; if (state == NEW) { return Thread.State.NEW; } else if (state == STARTED) { @@ -164,7 +171,9 @@ Thread.State threadState() { } else { return Thread.State.RUNNABLE; } - } else if (state == RUNNABLE || state == RUNNABLE_SUSPENDED) { + } else if (JDK21u3OrEarlier.jdk21u3OrEarlier && state == RUNNABLE) { + return Thread.State.RUNNABLE; + } else if (JDK21u4OrLater.jdk21u4OrLater && (state == UNPARKED || state == YIELDED)) { return Thread.State.RUNNABLE; } else if (state == RUNNING) { Object token = VirtualThreadHelper.acquireInterruptLockMaybeSwitch(this); @@ -179,7 +188,7 @@ Thread.State threadState() { return Thread.State.RUNNABLE; } else if (state == PARKING || state == YIELDING) { return Thread.State.RUNNABLE; - } else if (state == PARKED || state == PARKED_SUSPENDED || state == PINNED) { + } else if (state == PARKED || state == PINNED) { int parkedThreadStatus = MonitorSupport.singleton().getParkedThreadStatus(asThread(this), false); switch (parkedThreadStatus) { case ThreadStatus.BLOCKED_ON_MONITOR_ENTER: @@ -192,6 +201,12 @@ Thread.State threadState() { } } else if (state == TERMINATED) { return Thread.State.TERMINATED; + } else if (JDK21u4OrLater.jdk21u4OrLater) { + if (state == TIMED_PARKING) { + return Thread.State.RUNNABLE; + } else if (state == TIMED_PARKED || state == TIMED_PINNED) { + return Thread.State.TIMED_WAITING; + } } throw new InternalError(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java index 0a7b66da9b4..136bb0e53d7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java @@ -653,7 +653,15 @@ private static boolean isValid(Service s) { private static Function> getConstructorParameterClassAccessor(ImageClassLoader loader) { Map knownEngines = ReflectionUtil.readStaticField(Provider.class, "knownEngines"); Class clazz = loader.findClassOrFail("java.security.Provider$EngineDescription"); - Field consParamClassNameField = ReflectionUtil.lookupField(clazz, "constructorParameterClassName"); + Field consParamClassField; + + try { + consParamClassField = ReflectionUtil.lookupField(clazz, "constructorParameterClassName"); + } catch (ReflectionUtil.ReflectionUtilError e) { + consParamClassField = ReflectionUtil.lookupField(clazz, "constructorParameterClass"); + } + + final Field consParamClassFieldFinal = consParamClassField; /* * The returned lambda captures the value of the Provider.knownEngines map retrieved above @@ -678,9 +686,12 @@ private static Function> getConstructorParameterClassAccessor(I if (engineDescription == null) { return null; } - String constrParamClassName = (String) consParamClassNameField.get(engineDescription); - if (constrParamClassName != null) { - return loader.findClass(constrParamClassName).get(); + if (consParamClassFieldFinal.getName().equals("constructorParameterClass")) { + return (Class) consParamClassFieldFinal.get(engineDescription); + } + String constructorParameterClassName = (String) consParamClassFieldFinal.get(engineDescription); + if (constructorParameterClassName != null) { + return loader.findClass(constructorParameterClassName).get(); } } catch (IllegalAccessException e) { VMError.shouldNotReachHere(e); 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 efc47edece4..25e48044eb7 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); } diff --git a/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c b/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c index ad62c918051..9f20147f7f5 100644 --- a/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c +++ b/substratevm/src/com.oracle.svm.native.jvm.posix/src/JvmFuncs.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -311,10 +311,15 @@ JNIEXPORT jobject JNICALL JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject acti return (*env)->CallObjectMethod(env, action, run); } } + + /* Some error occurred - clear pending exception and try to report the error. */ + (*env)->ExceptionClear(env); + jclass errorClass = (*env)->FindClass(env, "java/lang/InternalError"); if (errorClass != NULL && !(*env)->ExceptionCheck(env)) { (*env)->ThrowNew(env, errorClass, "Could not invoke PrivilegedAction"); } else { + (*env)->ExceptionClear(env); (*env)->FatalError(env, "PrivilegedAction could not be invoked and the error could not be reported"); } return NULL; diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadId.c b/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadId.c index 4e60f087cf8..48421bb1ff2 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadId.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadId.c @@ -28,6 +28,7 @@ #include #include +#include /* * Based on os::Linux::gettid() from jdk-20-ga, see diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadUserTime.c b/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadUserTime.c index e33580a689a..17836710b5b 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadUserTime.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/getThreadUserTime.c @@ -26,6 +26,7 @@ #ifdef __linux__ +#include #include #include #include