【问题标题】:java.lang.ExceptionInInitializerError with Java-16 | j.l.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed modulejava.lang.ExceptionInInitializerError 与 Java-16 | j.l.ClassFormatError 可访问:模块 java.base 不会“打开 java.lang”到未命名的模块
【发布时间】:2021-07-02 14:28:42
【问题描述】:

我有 cglib 作为 Maven 项目中的传递依赖项。尽管添加了我认为正确的 --add-opens,但我无法让该库与 Java 16 一起使用。

如何让cglib 使用 Java 16?我在 github 页面上提出了this issue

最小的可重现示例:

Main.java

import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        new Enhancer();
    }
}

使用 Java 15:

javac -cp cglib-3.3.0.jar Main.java

java --add-opens java.base/java.lang=ALL-UNNAMED -cp cglib-3.3.0.jar:asm-7.1.jar:. Main

Picked up _JAVA_OPTIONS: -Duser.language=en -Duser.country=GB
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.sf.cglib.core.ReflectUtils$1 (file:/Users/rbain/Desktop/cglib-3.3.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of net.sf.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

使用 Java 16:

javac -cp cglib-3.3.0.jar Main.java

java --add-opens java.base/java.lang=ALL-UNNAMED -cp cglib-3.3.0.jar:asm-7.1.jar:. Main

Exception in thread "main" java.lang.ExceptionInInitializerError
    at Main.main(Main.java:5)
Caused by: net.sf.cglib.core.CodeGenerationException: 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 @11739fa6
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:464)
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:96)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:94)
    at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:119)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)
    at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)
    at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:174)
    at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:153)
    at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)
    ... 1 more
Caused by: 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 @11739fa6
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
    at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    at net.sf.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
    at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52)
    at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)
    at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)
    ... 13 more

【问题讨论】:

  • 你明白Rafael所说的“你可以更改禁止访问内部API的设置”吗?我没有,所以想知道
  • @Eugene 我不确定,但我认为他的意思是添加 --add-opens
  • 这看起来不像是“禁止”。可能他在谈论某些内部 cglib 标志?
  • Rafael 肯定是指--illegal-access=…。在 JDK 16 之前,它的默认值是 --illegal-access=permit,现在是 --illegal-access=deny。您可以覆盖它并获得一些时间,直到 JEP 403 被实施,整个事情将再次崩溃。
  • 长期的解决方案是更新cglib,不以这种方式使用内部 API 点,因为相对很快,变通方法将停止工作。您需要将此问题报告给cglib 维护者;这是他们要解决的问题。

标签: java cglib java-16


【解决方案1】:

自 JDK 16 起,--illegal-access 选项的默认值为 deny,因此对 JDK 类的“深度反射”失败。

您可以通过指定 --illegal-access=permit 来覆盖该行为,但您必须注意 JEP 403: Strongly Encapsulate JDK Internals 将在未来版本中关闭这种可能性,因此此选项只是一个临时解决方案。

永久的解决方案是将 cglib 更新为兼容版本(如果/一旦存在)。访问ClassLoader.defineClass 的尝试表明该库想要将类添加到特定的上下文中,这可以通过MethodHandles.lookup().defineClass 来完成(从Java 9 开始)。所以代码只需要切换到新的添加类的方式。

【讨论】:

  • 仅供参考,冒昧地将此引用回问题中链接的 GitHub 问题,以供未来的观众使用
猜你喜欢
  • 2021-09-08
  • 2022-08-09
  • 2021-10-28
  • 2021-09-20
  • 1970-01-01
  • 2019-07-17
  • 2023-02-20
  • 2017-07-28
  • 1970-01-01
相关资源
最近更新 更多