Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraalVM-built native image does not support Unsafe.staticFieldOffset() method #2694

Closed
rpuch opened this issue Jul 20, 2020 · 10 comments
Closed

Comments

@rpuch
Copy link

rpuch commented Jul 20, 2020

Describe the issue

Unsafe.staticFieldOffset() causes an exception when invoked inside a native image:

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 Test.main(Test.java:9)

Steps to reproduce the issue

  1. Save the following program to Test.java:
import sun.misc.Unsafe;
import java.lang.reflect.*;

public class Test {
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        long offset = unsafe.staticFieldOffset(unsafeField);
        System.out.println(offset);
    }
}
  1. Run javac Test.java
  2. Run java Test to verify that it works (it does)
  3. Run native-image --no-server --no-fallback Test app
  4. Run ./app

Describe GraalVM and your environment:

I tried both the latest released version (20.1)

openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)

and the latest snapshot version (20.2):

openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 20.2.0-dev (build 11.0.7+10-jvmci-20.2-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.2.0-dev (build 11.0.7+10-jvmci-20.2-b02, mixed mode, sharing)

JDK version is 11

OS is Ubuntu Linux 16.04, kernel version 4.15.0-107-generic

Architecture is Amd64.

@rpuch
Copy link
Author

rpuch commented Jul 20, 2020

Actually, I'm not sure whether it is a bug or not. If it is 'just not implemented yet', are there any plans to support this feature? If I just do something wrong, please let me know.

Unsafe.staticFieldOffset() is used by Netty, for instance: https://github.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/internal/PlatformDependent0.java

@rpuch
Copy link
Author

rpuch commented Jul 21, 2020

When I add

[
{
  "name":"sun.misc.Unsafe",
  "fields":[{"name":"theUnsafe", "allowUnsafeAccess" : true}]
}
]

to reflect-config.json in an attempt to let native-image know that Unsafe access is needed to the field, I get the following error during native-image invocation:

Fatal error:jdk.vm.ci.common.JVMCIError: should not reach here: Unsafe access of static fields is not supported.
	at jdk.internal.vm.ci/jdk.vm.ci.common.JVMCIError.shouldNotReachHere(JVMCIError.java:48)
	at com.oracle.graal.pointsto.meta.AnalysisField.registerAsUnsafeAccessed(AnalysisField.java:267)
	at com.oracle.graal.pointsto.meta.AnalysisField.registerAsUnsafeAccessed(AnalysisField.java:261)
	at com.oracle.svm.hosted.FeatureImpl$BeforeAnalysisAccessImpl.registerAsUnsafeAccessed(FeatureImpl.java:327)

So it looks like Unsafe field offsets are not supported in native mode on purpose. Still, it's interesting to know why and whether this will change in the future.

@cstancu
Copy link
Member

cstancu commented Sep 23, 2020

Fixed by 46cd5c7.

@cstancu cstancu closed this as completed Sep 23, 2020
@rpuch
Copy link
Author

rpuch commented Sep 27, 2020

@cstancu The commit you mentioned 46cd5c7 was made on July, 17, so it seems that the issue should be fixed in the nightly builds for a looong time. But it is still present in the nightly build I downloaded today.

I've put together a demo project: https://github.com/rpuch/native-unsafe-static-field-offset

GraalVM's java identifies itself as follows:

openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment GraalVM CE 20.3.0-dev (build 11.0.8+10-jvmci-20.3-b01)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0-dev (build 11.0.8+10-jvmci-20.3-b01, mixed mode, sharing)

I did not find a way to reopen the issue. Could please anyone do it?

@HeikoBornholdt
Copy link

The issue persists in current GraalVM versions as well:

openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment GraalVM CE 21.0.0 (build 11.0.10+8-jvmci-21.0-b06)
OpenJDK 64-Bit Server VM GraalVM CE 21.0.0 (build 11.0.10+8-jvmci-21.0-b06, mixed mode, sharing)

@cstancu
Copy link
Member

cstancu commented Apr 7, 2021

You are right, that commit only updated the internal mechanism to properly support Unsafe.staticFieldOffset(). The missing substitutions have been added in f97bdb5.

@makingthematrix
Copy link

@cstancu : Hey, thanks for the fix! :) It looks like this fix is also important for making Scala 3 work with GraalVM native image. Currently, with GraalVM 21.1.0, I'm getting this error:

[INFO] [SUB] Exception in thread "main" scala.runtime.LazyVals$$anon$1
[INFO] [SUB] 	at scala.runtime.LazyVals$.$init$$$anonfun$3(LazyVals.scala:18)
[INFO] [SUB] 	at scala.Option.getOrElse(Option.scala:201)
[INFO] [SUB] 	at scala.runtime.LazyVals$.<clinit>(LazyVals.scala:19)
[INFO] [SUB] 	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
[INFO] [SUB] 	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
[INFO] [SUB] 	at calculator.Main.<clinit>(Main.scala:16)
[INFO] [SUB] 	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
[INFO] [SUB] 	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)

where the code in the class LazyVals depends on sun.misc.Unsafe. (https://github.com/lampepfl/dotty/blob/master/library/src/scala/runtime/LazyVals.scala)

Do you maybe have an idea when this fix will land in production?

@kpodsiad
Copy link

@makingthematrix I had the very same error (Scala 3, GraalVM CE 21.1.0) but I managed to run native image successfully. Are you sure that you passed reflect-config.json to the native-image command?

@makingthematrix
Copy link

@makingthematrix I had the very same error (Scala 3, GraalVM CE 21.1.0) but I managed to run native image successfully. Are you sure that you passed reflect-config.json to the native-image command?

I'm sure I don't do that :) why? and how?

@kpodsiad
Copy link

I'm terrible at writing explanations so see this and this2 in order to find answers how & why ;)
Hope these links will help you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants