网页无法调用java9_反射-如何解决Java 9上的InaccessibleObjectException(“无法使{member}可访问:模块{A}不会'打开{package}'到{B}'”)?...

该异常是由Java 9中引入的Java平台模块系统引起的,尤其是其强封装的实现。它仅允许在特定条件下访问,最突出的条件是:

类型必须是公开的

拥有包必须导出

对于反射,导致异常的代码尝试使用相同的限制。更确切地说,该异常是由对open module {A} { ... }的调用引起的。在上面的堆栈跟踪中可以看到这一点,其中open module {A} { ... }中的相应行如下所示:

static void setAccessible(final AccessibleObject ao,

final boolean accessible) {

if (System.getSecurityManager() == null)

ao.setAccessible(accessible); //

else {

AccessController.doPrivileged(new PrivilegedAction() {

public Object run() {

ao.setAccessible(accessible); //

return null;

}

});

}

}

为了确保程序成功运行,必须说服模块系统允许访问调用了open module {A} { ... }064的元素。所需的所有信息都包含在异常消息中,但是有许多机制可以实现此目的。哪一个最好,取决于导致它的确切情况。

无法使{member}可以访问:模块{A}不能向{B}打开{package}

到目前为止,最突出的方案是以下两种:

库或框架使用反射来调用JDK模块。在这种情况下:

open module {A} { ... }是Java模块(以{B}或jdk.为前缀)

open module {A} { ... }和{B}是Java API的一部分

open module {A} { ... }是一个库,框架或应用程序模块; 经常{B}

基于反射的库/框架(例如Spring,Hibernate,JAXB等)在应用程序代码上进行反射,以访问bean,实体等。在这种情况下:

open module {A} { ... }是一个应用程序模块

open module {A} { ... }和{B}是应用程序代码的一部分

open module {A} { ... }是框架模块或{B}

请注意,某些库(例如JAXB)在两个帐户上都可能失败,因此请仔细查看您所处的场景!问题中的一个是案例1。

1.反射调用JDK

JDK模块对于应用程序开发人员而言是不变的,因此我们无法更改其属性。这仅留下一种可能的解决方案:命令行标志。有了它们,就有可能打开特定的包装以进行反思。

因此,在上述情况下(缩短)...

无法使java.lang.ClassLoader.defineClass可访问:模块java.base不会“打开java.lang”到未命名的模块@ 1941a8ff

...正确的解决方法是按以下方式启动JVM:

# --add-opens has the following syntax: {A}/{package}={B}

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

如果反射代码在命名模块中,则可以用其名称替换open module {A} { ... }。

请注意,有时可能很难找到一种将该标志应用于将实际执行反射代码的JVM的方法。如果所涉及的代码是项目构建过程的一部分,并且在构建工具产生的JVM中执行,则这可能会特别困难。

如果要添加的标志太多,则可以考虑使用封装终止开关open module {A} { ... }。 它将允许类路径上的所有代码反映所有已命名的模块。 请注意,此标志仅在Java 9中有效!

2.对应用程序代码的反思

在这种情况下,您很可能可以编辑用于反射的模块。(如果没有,则实际上是在情况1中。)这意味着不需要命令行标志,而是可以使用模块open module {A} { ... }的描述符打开其内部。有多种选择:

导出带有open module {A} { ... }的程序包,使其在编译和运行时可用于所有代码

使用2706162518918959064064将程序包导出到访问模块,这使其在编译和运行时可用,但仅对{B}

使用open module {A} { ... }0打开软件包,这使得它在运行时(带或不带反射)可用于所有代码

使用open module {A} { ... }将程序包打开到访问模块,这将使其在运行时可用(有或没有反射),但仅适用于{B}

使用2706162518959059064064打开整个模块,这将使其所有软件包在运行时对所有代码可用(带或不带反射)

有关这些方法的更详细的讨论和比较,请参见这篇文章。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值