Do not try to use Unsafe.staticFieldOffset() method under a native image. (#10428)

Motivation:

GraalVM's native images built with native-image tool do not support Unsafe.staticFieldOffset() method (at least, currently). If an application using Netty (and causing initialization of io.netty.util.internal.PlatformDependent0 class) is built into a native image and run, this results in the following error thrown during initialization:

Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: Unsupported method of Unsafe
	at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:86)
	at jdk.internal.misc.Unsafe.staticFieldOffset(Unsafe.java:230)
	at sun.misc.Unsafe.staticFieldOffset(Unsafe.java:662)
	at io.netty.util.internal.PlatformDependent0$5.run(PlatformDependent0.java:294)
	at java.security.AccessController.doPrivileged(AccessController.java:83)
	at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:279)

This seems to be the reason of the behavior described in #10051.

Modification:

The idea of this commit is to only invoke Unsafe.staticFieldOffset() is we are not in a native image; if we are, behave like if we could not find the field at all.

GraalDetector is borrowed from Spring framework.

Result:

Fixes #10051
This commit is contained in:
Roman Puchkovskiy 2020-08-03 21:49:06 +04:00 committed by GitHub
parent c4754cf7b8
commit 0601389766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -53,6 +53,11 @@ final class PlatformDependent0 {
private static final Object INTERNAL_UNSAFE;
private static final boolean IS_EXPLICIT_TRY_REFLECTION_SET_ACCESSIBLE = explicitTryReflectionSetAccessible0();
// See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/
// ImageInfo.java
private static final boolean RUNNING_IN_NATIVE_IMAGE = SystemPropertyUtil.contains(
"org.graalvm.nativeimage.imagecode");
static final Unsafe UNSAFE;
// constants borrowed from murmur3
@ -283,7 +288,7 @@ final class PlatformDependent0 {
Class<?> bitsClass =
Class.forName("java.nio.Bits", false, getSystemClassLoader());
int version = javaVersion();
if (version >= 9) {
if (unsafeStaticFieldOffsetSupported() && version >= 9) {
// Java9/10 use all lowercase and later versions all uppercase.
String fieldName = version >= 11 ? "UNALIGNED" : "unaligned";
// On Java9 and later we try to directly access the field as we can do this without
@ -399,6 +404,10 @@ final class PlatformDependent0 {
DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable");
}
private static boolean unsafeStaticFieldOffsetSupported() {
return !RUNNING_IN_NATIVE_IMAGE;
}
static boolean isExplicitNoUnsafe() {
return EXPLICIT_NO_UNSAFE_CAUSE != null;
}