From 9c1f913afd2517322401a1073580069abc91d916 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Tue, 13 May 2025 11:18:18 +0200 Subject: [PATCH 1/2] Remove JDK21OrEarlier from Web Image --- .../system/WebImageIOSubstitutions.java | 10 ---- .../system/WebImageSecuritySubstitutions.java | 48 ------------------- .../system/WebImageUnixIOSubstitutions.java | 37 +------------- 3 files changed, 1 insertion(+), 94 deletions(-) diff --git a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageIOSubstitutions.java b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageIOSubstitutions.java index 410153ba0d37..d81631ce91f7 100644 --- a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageIOSubstitutions.java +++ b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageIOSubstitutions.java @@ -52,8 +52,6 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.annotate.TargetElement; -import com.oracle.svm.core.jdk.JDK21OrEarlier; -import com.oracle.svm.core.jdk.JDKLatest; import com.oracle.svm.core.util.VMError; import com.oracle.svm.webimage.fs.WebImageNIOFileSystemProvider; import com.oracle.svm.webimage.functionintrinsics.JSFunctionIntrinsics; @@ -175,7 +173,6 @@ private long length0() { } @Substitute - @TargetElement(onlyWith = JDKLatest.class) @SuppressWarnings({"static-method"}) private boolean isRegularFile() { return !fd.equals(FileDescriptor.in); @@ -414,13 +411,6 @@ public int read(ByteBuffer var1) throws IOException { } @Substitute - @TargetElement(name = "open", onlyWith = JDK21OrEarlier.class) - public static FileChannel openJDK21(FileDescriptor fd, String path, boolean readable, boolean writable, boolean direct, Closeable parent) { - throw new UnsupportedOperationException("FileChannelImpl.open"); - } - - @Substitute - @TargetElement(onlyWith = JDKLatest.class) public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, boolean sync, boolean direct, Closeable parent) { throw new UnsupportedOperationException("FileChannelImpl.open"); } diff --git a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageSecuritySubstitutions.java b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageSecuritySubstitutions.java index 0a351bae3e3e..0fd1bd3bf449 100644 --- a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageSecuritySubstitutions.java +++ b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageSecuritySubstitutions.java @@ -25,17 +25,11 @@ package com.oracle.svm.webimage.substitute.system; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import java.util.function.BooleanSupplier; import com.oracle.svm.core.annotate.Delete; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.jdk.JDK21OrEarlier; import com.oracle.svm.webimage.substitute.WebImageUtil; import sun.security.provider.NativePRNG; @@ -43,48 +37,6 @@ public class WebImageSecuritySubstitutions { } -@TargetClass(value = AccessController.class, onlyWith = JDK21OrEarlier.class) -final class Target_java_security_AccessController_Web { - - /** - * We need this substitution to avoid doing a stack walk. - */ - @Substitute - static T doPrivileged(PrivilegedAction action, - @SuppressWarnings("unused") AccessControlContext context, @SuppressWarnings("unused") Permission... perms) { - return action.run(); - } - - @Substitute - static AccessControlContext getStackAccessControlContext() { - return null; - } - - @Substitute - @SuppressWarnings({"deprecation", "unused"}) // deprecated starting JDK 17 - static T executePrivileged(PrivilegedExceptionAction action, AccessControlContext context, Class caller) throws Throwable { - if (action == null) { - throw new NullPointerException("Null action"); - } - - if (action == null) { - throw new NullPointerException("Null action"); - } - - return action.run(); - } - - @Substitute - @SuppressWarnings({"deprecation", "unused"}) // deprecated starting JDK 17 - static T executePrivileged(PrivilegedAction action, AccessControlContext context, Class caller) throws Throwable { - if (action == null) { - throw new NullPointerException("Null action"); - } - - return action.run(); - } -} - // Windows does not have a NativePRNG implementation @TargetClass(value = NativePRNG.class, onlyWith = IsUnix.class) @SuppressWarnings("all") diff --git a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageUnixIOSubstitutions.java b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageUnixIOSubstitutions.java index 0d3cbbd74cee..fdfcf6c8a449 100644 --- a/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageUnixIOSubstitutions.java +++ b/web-image/src/com.oracle.svm.webimage/src/com/oracle/svm/webimage/substitute/system/WebImageUnixIOSubstitutions.java @@ -32,9 +32,6 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.annotate.TargetElement; -import com.oracle.svm.core.jdk.JDK21OrEarlier; -import com.oracle.svm.core.jdk.JDKLatest; /* * Checkstyle: stop method name check @@ -83,12 +80,6 @@ static void unlink0(long l) { throw new UnsupportedOperationException("UnixNativeDispatcher.unlink"); } - @Substitute - @TargetElement(onlyWith = JDK21OrEarlier.class) - static void futimes(int fd, long times0, long times1) { - throw new UnsupportedOperationException("UnixNativeDispatcher.futimes"); - } - @Substitute static void fchmod(int fd, int mode) { throw new UnsupportedOperationException("UnixNativeDispatcher.fchmod"); @@ -160,31 +151,11 @@ static int fgetxattr0(int filedes, long nameAddress, long valueAddress, int valu } @Substitute - @TargetElement(onlyWith = JDKLatest.class, name = "access0") - static int access0JDK23(long pathAddress, int amode) { - throw new UnsupportedOperationException("UnixNativeDispatcher.access0"); - } - - @Substitute - @TargetElement(onlyWith = JDK21OrEarlier.class) - static void access0(long pathAddress, int amode) { + static int access0(long pathAddress, int amode) { throw new UnsupportedOperationException("UnixNativeDispatcher.access0"); } @Substitute - @TargetElement(onlyWith = JDK21OrEarlier.class) - static boolean exists0(long pathAddress) { - throw new UnsupportedOperationException("UnixNativeDispatcher.exists0"); - } - - @Substitute - @TargetElement(onlyWith = JDK21OrEarlier.class) - static void utimes0(long pathAddress, long times0, long times1) { - throw new UnsupportedOperationException("UnixNativeDispatcher.utimes0"); - } - - @Substitute - @TargetElement(onlyWith = JDKLatest.class) private static void utimensat0(int fd, long pathAddress, long times0, long times1, int flags) { throw new UnsupportedOperationException("UnixNativeDispatcher.utimensat0"); } @@ -219,12 +190,6 @@ static void mknod0(long pathAddress, int mode, long dev) { throw new UnsupportedOperationException("UnixNativeDispatcher.mknod0"); } - @Substitute - @TargetElement(onlyWith = JDK21OrEarlier.class) - static void lutimes0(long pathAddress, long times0, long times1) { - throw new UnsupportedOperationException("UnixNativeDispatcher.lutimes0"); - } - @Substitute static void lchown0(long pathAddress, int uid, int gid) { throw new UnsupportedOperationException("UnixNativeDispatcher.lchown0"); From 348d68c3bb2cc8c53fba918f30eee5814b2c6fb6 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Tue, 13 May 2025 13:25:08 +0200 Subject: [PATCH 2/2] Remove JDK21 specific BaseLocale cache code We still have to use reflection because spotbugs still runs on JDK21 --- .../svm/hosted/webimage/WebImageFeature.java | 59 ++++++++----------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java index 9140cff138b5..9f3b6c5e3be1 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java @@ -112,7 +112,6 @@ import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.util.Providers; -import jdk.graal.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @AutomaticallyRegisteredFeature @@ -191,45 +190,33 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { * the cost of having to recreate the Locale and BaseLocale objects once when they're * requested. * - * On JDK21, ReferencedKeySet and ReferencedKeyMap don't exist, so we can't reference them - * directly and have to go through reflection. + * On JDK21, ReferencedKeySet and ReferencedKeyMap don't exist. We have to go through + * reflection to access them because analysis tools like spotbugs still run on JDK21 */ - if (JavaVersionUtil.JAVA_SPEC > 21) { - Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale$1InterningCache", "CACHE"); - Field localeCacheField = accessImpl.findField("java.util.Locale$LocaleCache", "LOCALE_CACHE"); - - access.registerFieldValueTransformer(baseLocaleCacheField, (receiver, originalValue) -> { - /* - * Executes `ReferencedKeySet.create(true, - * ReferencedKeySet.concurrentHashMapSupplier())` with reflection. - */ - Class referencedKeySetClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet"); - Method createMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "create", boolean.class, Supplier.class); - Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "concurrentHashMapSupplier"); - return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); - }); - - access.registerFieldValueTransformer(localeCacheField, (receiver, originalValue) -> { - /* - * Executes `ReferencedKeyMap.create(true, - * ReferencedKeyMap.concurrentHashMapSupplier())` with reflection. - */ - Class referencedKeyMapClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeyMap"); - Method createMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "create", boolean.class, Supplier.class); - Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "concurrentHashMapSupplier"); - return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); - }); - } else { + Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale$1InterningCache", "CACHE"); + Field localeCacheField = accessImpl.findField("java.util.Locale$LocaleCache", "LOCALE_CACHE"); + + access.registerFieldValueTransformer(baseLocaleCacheField, (receiver, originalValue) -> { /* - * These fields contain an instance of the declaring class (Cache). It has a default - * constructor that we can invoke to create an empty cache. + * Executes `ReferencedKeySet.create(true, + * ReferencedKeySet.concurrentHashMapSupplier())` with reflection. */ - Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale$Cache", "CACHE"); - Field localeCacheField = accessImpl.findField("java.util.Locale$Cache", "LOCALECACHE"); + Class referencedKeySetClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet"); + Method createMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "create", boolean.class, Supplier.class); + Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "concurrentHashMapSupplier"); + return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); + }); - access.registerFieldValueTransformer(baseLocaleCacheField, (receiver, originalValue) -> ReflectionUtil.newInstance(originalValue.getClass())); - access.registerFieldValueTransformer(localeCacheField, (receiver, originalValue) -> ReflectionUtil.newInstance(originalValue.getClass())); - } + access.registerFieldValueTransformer(localeCacheField, (receiver, originalValue) -> { + /* + * Executes `ReferencedKeyMap.create(true, + * ReferencedKeyMap.concurrentHashMapSupplier())` with reflection. + */ + Class referencedKeyMapClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeyMap"); + Method createMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "create", boolean.class, Supplier.class); + Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "concurrentHashMapSupplier"); + return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); + }); } @Override