当前位置: 首页 > 知识库问答 >
问题:

如何解决在Java9上无法使{成员}可访问:模块{A}不'打开{包}'到{B})?

师建德
2023-03-14

在Java 9上运行应用程序时,在各种各样的场景中都会发生此异常。某些库和框架(Spring、Hibernate、JAXB)特别容易使用它。下面是来自Javassist的一个示例

java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @1941a8ff
    at java.base/jdk.internal.reflect.Reflection.throwInaccessibleObjectException(Reflection.java:427)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:201)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:192)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:186)
    at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:102)
    at javassist.util.proxy.FactoryHelper.toClass2(FactoryHelper.java:180)
    at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:163)
    at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:501)
    at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:486)
    at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:422)
    at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:394)

消息说:

无法使受保护的最终java.lang.类java.lang.ClassLoader.define类(java.lang.String, byte[], int, int,java.security.protected Domain)抛出java.lang.ClassFormatError可访问:模块java.base不"打开java.lang"到未命名的模块@1941a8ff

如何避免异常并使程序成功运行?

共有3个答案

淳于恺
2023-03-14

在eclipse.ini中添加java.base/java.lang=ALL-UNNAMED

陈宏胜
2023-03-14

使用--add opens应该被视为一种变通方法。正确的做法是Spring、Hibernate和其他进行非法访问的库修复它们的问题。

武友樵
2023-03-14

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

  • 类型必须是公共的
  • 必须导出拥有包

同样的限制也适用于反射,导致异常的代码试图使用反射。更准确地说,异常是由调用setAccessible引起的。这可以在上面的堆栈跟踪中看到,其中javassist中的对应行。util。代理安全措施如下所示:

static void setAccessible(final AccessibleObject ao,
                          final boolean accessible) {
    if (System.getSecurityManager() == null)
        ao.setAccessible(accessible); // <~ Dragons
    else {
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ao.setAccessible(accessible);  // <~ moar Dragons
                return null;
            }
        });
    }
}

为了确保程序成功运行,必须说服模块系统允许访问调用的元素。所有需要的信息都包含在异常消息中,但是有许多机制可以实现这一点。哪个是最好的取决于导致它的确切场景。

无法使{member}可访问:模块{A}没有将{package}打开到{B}

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

>

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

    • {A}是一个Java模块(前缀为Java.jdk.

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

    • {A}是一个应用程序模块
    • {member}{package}是应用程序代码的一部分
    • {B}是框架模块或未命名模块@

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

    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
    

    如果反射代码位于命名模块中,ALL-UNNAMED可替换为其名称。

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

    如果有太多的标志要添加,你可以考虑使用封装杀死开关<代码> -允许非法访问< /代码>。它将允许类路径上的所有代码反映整个命名模块。请注意,此标志仅在Java9中有效!

    在这个场景中,您可能可以编辑反射用来闯入的模块。(如果不是,则在案例1中,您将有效地执行此操作。)这意味着不需要命令行标志,相反,可以使用模块{A}的描述符来打开其内部。有多种选择:

    • 导出包与导出{包},这使得它在编译和运行时可用于所有代码
    • 将包导出到访问模块,并将{包导出到{B},这使得它在编译和运行时可用,但仅适用于{B}
    • 打开包打开{pack},这使得它在运行时(有或没有反射)对所有代码可用
    • 打开包到访问模块打开{pack}到{B},这使得它在运行时(有或没有反射)可用,但仅对{B}
    • 用打开模块{A}{...}打开整个模块,这使得它的所有包在运行时(有或没有反射)对所有代码可用

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

  •  类似资料:
    • 手机用aidlux安装了amh,内网无法访问站点 内网访问站点显示拒绝连接,感觉是防火墙的问题,尝试去修改却一直出现“AMNetwork : 防火墙配置失败,请检查更改规则是否正确。”,安装了那个应用商店的alist网盘,从文件那个地方能够直接访问进去,并且正常上传和下载文件,不知道为啥访问不了创建的站点

    • 我试图使用java 9和gradle的Spring启动。我无法运行我的简单代码,我得到下面提到的错误:- 我的依赖文件和module-info.java文件非常简单。 有人能帮忙吗?? 谢谢 阿马尔

    • 非常简单的用例,我使用的是EclipseOxygen4.7。3a,包括来自Java9的支持。我有两个项目是Java 9项目: 我想在中使用类,因此我尝试将第二个模块导入第一个项目。 模块信息。java项目1: 模块信息。java项目2: Eclipse给了我错误: 项目二不能解析为模块 我是否必须将所有Java项目集中在一个“主项目”下,以便让Eclipse知道所有这些模块在其中都是可用的?还是我

    • 项目目录映像 我正在尝试使用以下语法在我的react应用程序中导入firebase: 从.../Firebase/config导入{auth} 但我面临以下问题: ./src/Pages/Login/Login.js模块未找到:无法解决.../Firebase/config 这是我的配置文件 从“/firebase/app”导入*firebase/auth”作为firebase;导入“fireba

    • pyqt5 使用pyinstaller打包,但是提示找不到本地模块,怎么解决呢。我本地有个views的目录,然后在入口main.py导入, 使用pyinstaller打包后,出现说找不到模块, 有大佬知道怎么解决吗? 查过很多资料,都没有用

    • 我们正在开发使用MongoDB作为存储的Spring Boot应用程序。我们想在项目中添加DB迁移工具:mongock。 在中,我添加了一个新的依赖项: IntelliJ Idea建议我在: 在此之后,我无法再构建项目,我得到以下错误: 我对Java9模块化不太了解,这就是为什么我一直在解决这个问题,请给出建议。

    • 我正在尝试创建一个JupyterLab扩展,它使用typescript。 我已经成功地添加了包“@类型/节点”,允许我使用诸如“要求”(“超文本传输协议”)这样的包。 但一旦我尝试使用子进程,使用“require”(“child_process”),我在尝试构建扩展时就会出现以下错误。 我在谷歌上搜索过,但仍然不知道如何解决这个问题。 如有任何提示或信息,将不胜感激。 我的包裹。json文件。

    • 尝试在JMX控制台中注册MBean时,我收到以下错误消息: 我正在使用Eclipse,我的项目结构中没有文件。 当我注释我对javaeeapi的依赖关系时,错误消失了,但是包不是JAR的一部分。