我在名为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);
}
}
它只是获取一个Unsafe
实例,然后调用其staticFieldOffset()
方法。
我用javac Test.java
进行编译,它会输出有关Unsafe
危险的警告。
然后,我使用java Test
运行生成的类文件并获得以下内容:
104
因此有效。
现在,我使用native-image --no-server --no-fallback Test app
构建本机映像。
[app:11806] classlist: 1,486.00 ms, 0.96 GB
[app:11806] (cap): 481.32 ms, 0.96 GB
[app:11806] setup: 1,628.06 ms, 0.96 GB
[app:11806] (clinit): 201.38 ms, 1.70 GB
[app:11806] (typeflow): 5,540.87 ms, 1.70 GB
[app:11806] (objects): 4,523.67 ms, 1.70 GB
[app:11806] (features): 251.65 ms, 1.70 GB
[app:11806] analysis: 10,741.48 ms, 1.70 GB
[app:11806] universe: 368.62 ms, 1.70 GB
[app:11806] (parse): 1,327.10 ms, 1.70 GB
[app:11806] (inline): 1,156.04 ms, 1.70 GB
[app:11806] (compile): 8,106.76 ms, 2.33 GB
[app:11806] compile: 10,998.36 ms, 2.33 GB
[app:11806] image: 765.81 ms, 2.33 GB
[app:11806] write: 137.50 ms, 2.33 GB
[app:11806] [total]: 26,315.42 ms, 2.33 GB
好吧,最后,我用./app
运行它。结果如下:
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)
因此,在纯模式下,它似乎不支持Unsafe.staticFieldOffset()
方法。
是否有使其工作的任何方法,还是应该在GraalVM代码中解决?这似乎阻碍了Netty在本机映像中的使用,请参见https://github.com/netty/netty/issues/10051作为示例。
我正在使用GraalVM 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)
PS 使用代理收集配置无济于事。也就是说,当我将-agentlib:native-image-agent=config-output-dir=target/config
添加到java
命令以收集有关反射和填充的运行时数据,然后将-H:ConfigurationFileDirectories=target/config
添加到native-image
命令时,生成的本机程序的行为相同