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

JPMS:--add-opens不适用于java.lang.reflect.InaccessibleObjectException

高恺
2023-03-14

我将Java14与Jetty 9.4和Weld-Servlet-Shaded-3.1一起使用,并得到以下异常:

Caused by: java.lang.reflect.InaccessibleObjectException: 
Unable to make protected final java.lang.Class   
java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
throws java.lang.ClassFormatError accessible: module java.base does 
not "opens java.lang" to module weld.servlet.shaded.

根据这里的答案:https://stackoverflow.com/a/41265267/5057736我试图添加

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

--add-opens java.base/java.lang=weld.servlet.shaded 

但没人帮忙。有人能说怎么修吗?

<compiler.source>1.8</compiler.source>
<compiler.target>1.8</compiler.target>
$ java -version
openjdk version "14" 2020-03-17
OpenJDK Runtime Environment (build 14+36-1461)
OpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)

启动应用程序

$java .... --add-opens java.base/java.lang=weld.servlet.shaded ...

这是堆栈跟踪

09:58:41.243 [RMI TCP Connection(2)-127.0.0.1] INFO  org.jboss.weld.environment.servletWeldServlet - WELD-ENV-001008: Initialize Weld using ServletContainerInitializer
09:58:41.293 [RMI TCP Connection(2)-127.0.0.1] INFO  org.jboss.weld.Version - WELD-000900: 3.1.0 (Final)
09:58:41.468 [RMI TCP Connection(2)-127.0.0.1] WARN  org.jboss.weld.environment.servletWeldServlet - WELD-ENV-001004: Found both WEB-INF/beans.xml and WEB-INF/classes/META-INF/beans.xml. It is not portable to use both locations at the same time. Weld is going to use: file:/home/<SOME TEXT DELETED>/webapp/WEB-INF/beans.xml
09:58:41.479 [RMI TCP Connection(2)-127.0.0.1] INFO  org.jboss.weld.Bootstrap - WELD-ENV-000014: Falling back to Java Reflection for bean-discovery-mode="annotated" discovery. Add org.jboss:jandex to the classpath to speed-up startup.
09:58:41.550 [RMI TCP Connection(2)-127.0.0.1] WARN  org.eclipse.jetty.annotations.ServletContainerInitializersStarter - 
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to module weld.servlet.shaded
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:349) ~[?:?]
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:289) ~[?:?]
    at java.lang.reflect.Method.checkCanSetAccessible(Method.java:196) ~[?:?]
    at java.lang.reflect.Method.setAccessible(Method.java:190) ~[?:?]
    at org.jboss.weld.util.bytecode.ClassFileUtils$1.run(ClassFileUtils.java:88) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at java.security.AccessController.doPrivileged(AccessController.java:554) ~[?:?]
    at org.jboss.weld.util.bytecode.ClassFileUtils.makeClassLoaderMethodsAccessible(ClassFileUtils.java:64) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldStartup.startContainer(WeldStartup.java:220) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldBootstrap.startContainer(WeldBootstrap.java:72) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldBootstrap.startContainer(WeldBootstrap.java:67) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.environment.servlet.WeldServletLifecycle.initialize(WeldServletLifecycle.java:182) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.environment.servlet.EnhancedListener.onStartup(EnhancedListener.java:62) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.eclipse.jetty.plus.annotation.ContainerInitializer.callStartup(ContainerInitializer.java:140) ~[jetty-plus-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.annotations.ServletContainerInitializersStarter.doStart(ServletContainerInitializersStarter.java:64) [jetty-annotations-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) [jetty-util-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:346) [jetty-servlet-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497) [jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459) [jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:852) [jetty-server-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278) [jetty-servlet-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545) [jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) [jetty-util-9.4.14.v20181114.jar:?]
    <SOME TEXT DELETED>
09:58:41.555 [RMI TCP Connection(2)-127.0.0.1] WARN  org.eclipse.jetty.webapp.WebAppContext - Failed startup of context o.e.j.w.WebAppContext@6a329710{/,file:///home//<SOME TEXT DELETED>/webapp/,UNAVAILABLE}{/home/<SOME TEXT DELETED>.war}
java.lang.RuntimeException: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to module weld.servlet.shaded
    at org.eclipse.jetty.annotations.ServletContainerInitializersStarter.doStart(ServletContainerInitializersStarter.java:69) ~[jetty-annotations-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) ~[jetty-util-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:346) ~[jetty-servlet-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497) ~[jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459) ~[jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:852) ~[jetty-server-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278) ~[jetty-servlet-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545) [jetty-webapp-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) [jetty-util-9.4.14.v20181114.jar:?]
    <SOME TEXT DELETED>
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to module weld.servlet.shaded
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:349) ~[?:?]
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:289) ~[?:?]
    at java.lang.reflect.Method.checkCanSetAccessible(Method.java:196) ~[?:?]
    at java.lang.reflect.Method.setAccessible(Method.java:190) ~[?:?]
    at org.jboss.weld.util.bytecode.ClassFileUtils$1.run(ClassFileUtils.java:88) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at java.security.AccessController.doPrivileged(AccessController.java:554) ~[?:?]
    at org.jboss.weld.util.bytecode.ClassFileUtils.makeClassLoaderMethodsAccessible(ClassFileUtils.java:64) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldStartup.startContainer(WeldStartup.java:220) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldBootstrap.startContainer(WeldBootstrap.java:72) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.bootstrap.WeldBootstrap.startContainer(WeldBootstrap.java:67) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.environment.servlet.WeldServletLifecycle.initialize(WeldServletLifecycle.java:182) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.jboss.weld.environment.servlet.EnhancedListener.onStartup(EnhancedListener.java:62) ~[weld-servlet-shaded-3.1.0.Final.jar:?]
    at org.eclipse.jetty.plus.annotation.ContainerInitializer.callStartup(ContainerInitializer.java:140) ~[jetty-plus-9.4.14.v20181114.jar:?]
    at org.eclipse.jetty.annotations.ServletContainerInitializersStarter.doStart(ServletContainerInitializersStarter.java:64) ~[jetty-annotations-9.4.14.v20181114.jar:?]
    ... 31 more

编辑4
我发现不同的行为发生,因为焊接。这是来自ClassFileUtils的文章:

public static void makeClassLoaderMethodsAccessible() {
    // the AtomicBoolean make sure this gets invoked only once as WeldStartup is triggered per deployment
    if (classLoaderMethodsMadeAccessible.compareAndSet(false, true)) {
        try {
            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                public Object run() throws Exception {
                    Class<?> cl = Class.forName("java.lang.ClassLoader");
                    final String name = "defineClass";

                    defineClass1 = cl.getDeclaredMethod(name, String.class, byte[].class, int.class, int.class);
                    defineClass2 = cl.getDeclaredMethod(name, String.class, byte[].class, int.class, int.class, ProtectionDomain.class);

                    // First try with Unsafe to avoid illegal access
                    try {
                        // get Unsafe singleton instance
                        Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
                        singleoneInstanceField.setAccessible(true);
                        Unsafe theUnsafe = (Unsafe) singleoneInstanceField.get(null);

                        // get the offset of the override field in AccessibleObject
                        long overrideOffset = theUnsafe.objectFieldOffset(AccessibleObject.class.getDeclaredField("override"));

                        // make both accessible
                        theUnsafe.putBoolean(defineClass1, overrideOffset, true);
                        theUnsafe.putBoolean(defineClass2, overrideOffset, true);
                        return null;
                    } catch (NoSuchFieldException e) {
                        // This is JDK 12+, the "override" field isn't there anymore, fallback to setAccessible()
LINE 88                 defineClass1.setAccessible(true);
                        defineClass2.setAccessible(true);
                        return null;
                    }
                }
            });
        } catch (PrivilegedActionException pae) {
            throw new RuntimeException("cannot initialize ClassPool", pae.getException());
        }
    }
}

共有1个答案

傅明知
2023-03-14

我发现有两个问题:

  1. 焊接ClassFileUtils.MakeClassLoaderMethodsAccessible()与JDK11和JDK12+的工作方式不同。
  2. --add-打开,因为CLI参数不适用于动态创建的层JPMs?在这里查看详细信息
 类似资料:
  • 问题内容: 在提交错误之前,我想请某人确认我最近遇到的奇怪行为。 考虑一下我们有一个简单的Dockerfile,我们试图将一些文件复制到非root用户的主目录中: 这就是我尝试构建此映像时得到的: 好像是空的。但为什么?将绝对路径放置到home目录而不是不是很方便。 问题答案: 这是您的问题: 使用指令时,它会影响用于在容器内启动新命令的用户标识。因此,例如,如果您这样做: 你得到这个: 因为这些

  • 我想在我分布在每个箭头中的应用程序中运行--add opens命令,但当我知道在本地添加它时,我不知道在云中添加它的位置 “无法读取JSON:无法使字段private final int java.time.LocalDate.year可访问” 我发现了错误 "https://stackoverflow.com/questions/70412805/what-does-this-error-mea

  • 我正在使用Java Webstart运行一个应用程序,但它需要在使用Java9+运行时打开一个模块:

  • 我最近与Quarkus一起玩过,并想尝试与之一起使用JPMS模块。 所以我去code.quarkus.io,生成了一个基本的应用程序,只启用了RESTEasy JAX-RS扩展。解包后,我所做的只是在中包含一个,并添加行。 现在,用Maven构建罐子很好。使用模式启动实时编码也可以正常工作。但是当我更改一些代码并尝试另一个请求时,我会得到一个错误页面,说明。 对我来说,Quarkus的开发模式似乎

  • 问题内容: 嗨,我只是简单地尝试在www.example.com上获取h1标签,该标签显示为“ Example Domain”。该代码适用于http://www.example.com,但不适用于https://www.exmaple.com。我该如何解决这个问题?谢谢 问题答案: PhantomJSDriver不支持(所有)DesiredCapabilities。 你会需要: 记录在这里:htt

  • 所以我使用这种方法写入文件,它在windows上运行完全正常,但在mac上运行时,它会创建文件,但它们是空的。 我知道数据是正确的,因为它打印正确。感谢您的任何帮助,这真的让我绊倒了。