java.lang.ExceptionInInitializerError 与 Java-16 | j.l.ClassFormatError 可访问的 : module java. 基础不 "opens java.lang"到未命名的模块

标签 java cglib java-16

我有 cglib作为 Maven 项目中的传递依赖项。尽管添加了我认为正确的 --add-opens我无法让该库与 Java 16 一起使用。
我如何获得 cglib使用 Java 16?我提出了this issue在 github 页面上。
最小的可重现示例: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.javajava --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.javajava --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

最佳答案

从 JDK 16 开始,--illegal-access 的默认值选项是 deny ,所以对 JDK 类的“深度反射”失败了。
您可以通过指定 --illegal-access=permit 来覆盖该行为。 ,但您必须注意 JEP 403: Strongly Encapsulate JDK Internals这是关于在 future 版本中关闭这种可能性,所以这个选项只是一个临时解决方案。
永久解决方案是将 cglib 更新为兼容版本(如果/一旦存在)。访问 ClassLoader.defineClass 的尝试建议库想要将类添加到特定的上下文中,这可以通过 MethodHandles.lookup().defineClass 完成。取而代之(从 Java 9 开始)。所以代码只需要切换到添加类的新方式。

关于java.lang.ExceptionInInitializerError 与 Java-16 | j.l.ClassFormatError 可访问的 : module java. 基础不 "opens java.lang"到未命名的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66974846/

相关文章:

java - 生成的查询包含架构和目录名称

java - 创建情绪分析工具

java - 每次调用其方法时都会重新创建 CGlib-wired bean

java - 使用基于 Java 的配置进行 Spring 3.2 单元测试

Java-Stream - 具有无限流的 mapMulti()

java - 返回类型为 void 的 switch 表达式

java - 如何为存储库设置特定的数据源?

java - 如果 Java 中的反射减慢了命令的执行速度,为什么还有那么多框架使用它?

Java 记录序列化和对规范构造函数的重复调用

java - 开始部署应用程序时,嵌入式 Tomcat 挂起