Netty-无法访问类jdk.internal.misc.Unsafe

49

当我将Java从8升级到11时,Netty报了一个关于"jdk.internal.misc.Unsafe"的错误,详情如下:

我知道这是一条调试级别消息,我可以更改日志级别以忽略它。但我不确定是否会出现其他问题 - 如性能 - 当我忽略它。有人知道这个问题的最佳解决方案吗?

java.lang.IllegalAccessException: class io.netty.util.internal.PlatformDependent0$6 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @84b8f0f
    at jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361) ~[?:?]
    at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:558) ~[?:?]
    at io.netty.util.internal.PlatformDependent0$6.run(PlatformDependent0.java:334) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:?]
    at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:325) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:214) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:82) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.buffer.UnpooledByteBufAllocator.<clinit>(UnpooledByteBufAllocator.java:37) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at io.netty.buffer.Unpooled.<clinit>(Unpooled.java:73) ~[netty-all-4.1.36.Final.jar:4.1.36.Final]
    at wedo.stream3.framework.base.connector.supplier.DelimiterDecoderSupplier.getDelimiter(DelimiterDecoderSupplier.java:41) ~[classes/:?]
    at wedo.stream3.framework.base.connector.supplier.DelimiterDecoderSupplier.<init>(DelimiterDecoderSupplier.java:26) ~[classes/:?]
    at wedo.stream3.framework.base.connector.supplier.DelimiterDecoderSupplier.<init>(DelimiterDecoderSupplier.java:20) ~[classes/:?]
    at wedo.stream3.framework.base.connector.supplier.CommonChannelHandlerSupplier.<init>(CommonChannelHandlerSupplier.java:37) ~[classes/:?]
    at wedo.stream3.framework.base.connector.supplier.CommonChannelHandlerSupplier.<init>(CommonChannelHandlerSupplier.java:25) ~[classes/:?]
    at wedo.stream3.framework.base.connector.TcpClientConnector.start(TcpClientConnector.java:39) ~[classes/:?]
    at wedo.stream3.framework.bootstrap.FrameworkLauncher.lambda$start$0(FrameworkLauncher.java:61) ~[classes/:?]
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) [?:?]
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) [?:?]
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654) [?:?]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) [?:?]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) [?:?]
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) [?:?]
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) [?:?]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) [?:?]
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) [?:?]
    at wedo.stream3.framework.bootstrap.FrameworkLauncher.start(FrameworkLauncher.java:58) [classes/:?]
    at org.stream3.prototype.mfc.App.launchFramework(App.java:58) [classes/:?]
    at org.stream3.prototype.mfc.App.main(App.java:41) [classes/:?]
5个回答

53

为了让netty可以访问该类,请使用以下选项启动Java:

--add-opens java.base/jdk.internal.misc=ALL-UNNAMED

这将把jdk.internal.misc包在java.base模块中打开给未命名模块。

另请参阅java命令的文档,以及一般情况下关于Java模块系统的介绍

编辑:为了让Netty使用其直接缓冲区优化,您还需要设置

-Dio.netty.tryReflectionSetAccessible=true

在这个问题上,有许多与Netty相关的问题,请参见例如netty/issues/7769


4
但是还有另一条信息留下来了:09:10:28.902 [main] DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: unavailable java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled有没有解决此问题的方法? - oarsmanli
1
这个问题在 netty 的 github 上有一个 issue: https://github.com/netty/netty/issues/7817 - gjoranv
1
非常感谢您。但是我想知道这个参数会影响性能吗? - oarsmanli
我没有答案,但我注意到你的Netty版本是从四月份的。升级到最新版本可能值得一试,看看问题是否已经解决:https://mvnrepository.com/artifact/io.netty/netty-all/4.1.41.Final - gjoranv
你如何将这些选项传递给运行的 mvn test 命令? - Kok How Teh
1
您可以在pom.xml中的maven-surefire-plugin配置中使用<argLine>。例如(对于糟糕的格式化表示抱歉):<configuration><argLine>--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED</argLine></configuration> - gjoranv

21

在Java 11上运行Netty时,请添加以下VM选项以启用性能优化:

--add-opens java.base/jdk.internal.misc=ALL-UNNAMED
-Dio.netty.tryReflectionSetAccessible=true

那么,为了知道何时使用深度反思,您可以添加:

--illegal-access=warn

5

就像您说的那样,这只是一条调试信息,可以忽略。它基本上告诉您Netty无法访问某个类,因此无法使用“所有优化”。但是,如果您愿意,可以通过命令行标志打开访问级别,在启动应用程序时进行。


这种优化是否应该默认启用?例如,它是否在某些官方指南中提到? - oligofren

3

Netty需要访问JDK模块,因此您需要在启动应用程序时添加JVM参数以允许访问。

--add-opens java.base/jdk.internal.misc=ALL-UNNAMED

此外,如果您想禁用“java.lang.UnsupportedOperationException:Reflective setAccessible(true)已禁用.....”警告堆栈跟踪,还可以包含以下内容:
-Dio.netty.tryReflectionSetAccessible=true

如果您正在使用Gradle构建工具,您可以按照以下方式在您的`build.gradle`文件中添加这些内容:
   distributions {
        applicationDefaultJvmArgs = ["--add-opens",
                                     "java.base/jdk.internal.misc=ALL-UNNAMED", "-Dio.netty.tryReflectionSetAccessible=true"]
        mainClassName = 'cl.domain.ServerLauncher'
        archivesBaseName = 'your-service'
        version = 'latest'
        main {
            baseName = 'your-service'
        }
    }

2

很遗憾,使用最新版本的io.grpc:grpc-netty-shaded:1.53.0,我发现你需要以下内容(与上述不同的标志名称),在Java 11上运行。

-Dio.grpc.netty.shaded.io.netty.tryReflectionSetAccessible=true
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED

正如您在源代码中所看到的,io.netty.tryReflectionSetAccessible不再是被检查的属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接