当前位置:首页 » 《资源分享》 » 正文

JKD17运行报错Unable to make field private final byte[] java.lang.String.value accessible

12 人参与  2024年05月12日 18:57  分类 : 《资源分享》  评论

点击全文阅读


之前使用jdk8的代码升级到jdk17运行报错信息如下:

Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[] java.lang.String.value accessible: module java.base does not "opens java.lang" to unnamed module @473b46c3at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)

大致意思就是通过反射获取String类中的私有字段byte[] value 失败了。

那怎么会这样呢,原因是:

在Java9之后引入了module模块的概念,而不同module模块间是不允许使用反射来访问非public的字段/方法/构造函数(field/method/constructor),除非被访问的目标模块为反射设置open即允许自身被其他模块进行non-public反射访问。

解决办法:

Java 9之后引入了一个新的JVM选项 --illegal-access,该选项有四个可选值:

permit:Jdk9、Jdk11的默认值,允许不同模块间进行non-public反射访问,且仅在首次非法访问会给出警告,后续不再警告。在该模式下会自动将Jdk8(或更低版本)的代码进行opens设置,即允许Jdk8的代码被其他模块进行non-public反射访问,也允许Jdk8的代码对其他模块进行non-public反射访问,如此可保证高、低版本混合的Java程序如往常一样正常运行。
warn:类似permit,但是每次非法访问都会警告
debug:类似warn,但在warn的基础上加入了类似e.printStackTrace()的功能
deny:未来的默认值,禁止所有的不同模块间的non-public反射访问,出现非法反射则抛出异常,除了使用特别的命令行参数排除的模块,比如使用 –add-opens排除某些模块使其能够通过非法反射访问
线上使用了--illegal-access=deny,所以出现非法反射时会导致程序抛异常而启动失败,
而本地开发环境运行程序时,未明确设置–illegal-access则使用默认--illegal-access=premit,所以可以启动成功,但在第一次非法反射访问时给出了警告。

综上,在设置了--illegal-access=deny(推荐设置deny,兼容未来Java版本)时,需同时添加--add-opens以开启对应模块/包允许被其他模块进行非法(non-public)反射访问。

例如根据之前的日志:

Unable to make field private final byte[] java.lang.String.value accessible:      
module java.base does not "opens java.lang" to unnamed module @1b70203f     

将关键提示日志拆解后如下表:

被访问模块名被访问包名发起非法访问的模块名
modulejava.basedoes not“opens java.lang”tounnamed module @473b46c3


具体转换格式:--add-opens 被访问模块名/被访问包名=发起非法访问的模块名

根据如上日志转换如下--add-opens命令为:

--add-opens java.base/java.long=ALL-UNNAMED


注: ALL-UNNAMED表示所有的未命名模块

反复重启根据提示最终整理如下完整--add-opens选项:

--illegal-access=deny--add-opens java.base/java.lang=ALL-UNNAMED--add-opens java.base/java.lang.reflect=ALL-UNNAMED--add-opens java.base/java.lang.invoke=ALL-UNNAMED--add-opens java.base/java.math=ALL-UNNAMED--add-opens java.base/java.util=ALL-UNNAMED--add-opens java.base/java.util.concurrent=ALL-UNNAMED--add-opens java.base/java.net=ALL-UNNAMED--add-opens java.base/java.text=ALL-UNNAMED


如上完整启动选项添加到vm参数中后,程序可以正常启动了。


点击全文阅读


本文链接:http://zhangshiyu.com/post/107577.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1