KOCA application&sample适配Java11&17

此文档写于:2022-10,所在版本:koca 3.6.0-SNAPSHOT

本教程适用于 koca-base、koca-boot、koca-cloud、koca-admin (统称为基础包)在 Java 8 环境下 install 为 jar 的形式提供给 koca-application、koca-sample 在 Java11 或 Java 17 环境下运行。

经测试,基础包 在 Java 8 环境为 install 操作后,都可正常运行通过。

@[TOC]

koca-application & sample 在 Java 11 环境运行

1. koca-application

  • 在 koca-cloud-admin-bootapp 下的 application.yml 增加解析 bex 的配置

    koca:
      bex:
        enabled: true
        bex-path: classpath*:/bex/*-bex.xml
    
  • 在 koca-admin-bootapp 下的 bootstrap.yml 增加解析 bex 的配置

    koca:
      bex:
        enabled: true
        bex-path: classpath*:/bex/*-bex.xml
    

2. koca-sample

1、koca-log-sample - log-separate-samples - business - BusinessApplication

  • 启动报错:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
    
  • 原因:Java11 中不包含 javax.xml.bind 包

  • 解决方法:在 pom.xml 加入

    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-ri</artifactId>
        <version>2.3.3</version>
        <type>pom</type>
    </dependency>
    

2、koca-other-samples - koca-config-server-sample

  • 启动报错:

    Caused by: java.net.URISyntaxException: Illegal character in opaque part at index 11: jar:file:D:\repo\com\szkingdom\koca\cloud\koca-cloud-config-server\3.6.0-SNAPSHOT\koca-cloud-config-server-3.6.0-SNAPSHOT.jar!/bex/config-audit-bex.xml
    
  • 原因:bex解析异常

  • 解决方法:

    koca:
      bex:
        enabled: true
        bex-path: classpath*:/bex/*-bex.xml
    

koca-application & sample 在 Java 17 环境运行

1. koca-application

  • 在 koca-cloud-admin-bootapp 下的 application.yml 增加解析 bex 的配置

    koca:
      bex:
        enabled: true
        bex-path: classpath*:/bex/*-bex.xml
    
  • 在 koca-admin-bootapp 下的 bootstrap.yml 增加解析 bex 的配置

    koca:
      bex:
        enabled: true
        bex-path: classpath*:/bex/*-bex.xml
    
  • koca-cloud-admin-bootapp、koca-admin-bootapp 都需要在启动的VM选项中加上:

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

2. koca-sample

  • koca-sample 必须在上述 Java 11 测试改动的基础上作出相应的修改,才能成功运行其程序。

  • 在 Java17 环境下,大多 启动类 出现如下问题:

    如:ServerApplication

    Caused by: java.lang.IllegalStateException: Failed to create adaptive instance: java.lang.IllegalStateException: Can't create adaptive extension interface org.apache.dubbo.rpc.Protocol, cause: 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 @1757cd72
    	at org.apache.dubbo.common.extension.ExtensionLoader.getAdaptiveExtension(ExtensionLoader.java:568) ~[dubbo-2.7.6.jar:2.7.6]
    	at org.apache.dubbo.config.ServiceConfig.<clinit>(ServiceConfig.java:118) ~[dubbo-2.7.6.jar:2.7.6]
    	... 23 common frames omitted
    Caused by: java.lang.IllegalStateException: Can't create adaptive extension interface org.apache.dubbo.rpc.Protocol, cause: 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 @1757cd72
    	at org.apache.dubbo.common.extension.ExtensionLoader.createAdaptiveExtension(ExtensionLoader.java:980) ~[dubbo-2.7.6.jar:2.7.6]
    	at org.apache.dubbo.common.extension.ExtensionLoader.getAdaptiveExtension(ExtensionLoader.java:564) ~[dubbo-2.7.6.jar:2.7.6]
    	... 24 common frames omitted
    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 @1757cd72
    	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na]
    	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na]
    	at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199) ~[na:na]
    

    如:KocaServerApplication

    java.lang.reflect.InaccessibleObjectException: Unable to make field private transient volatile java.lang.reflect.Parameter[] java.lang.reflect.Executable.parameters accessible: module java.base does not "opens java.lang.reflect" to unnamed module @192d43ce
    	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na]
    	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na]
    	at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178) ~[na:na]
    	at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) ~[na:na]
    	at com.fasterxml.jackson.databind.util.ClassUtil.checkAndFixAccess(ClassUtil.java:987) ~[jackson-databind-2.12.6.1.jar:2.12.6.1]
    
    Caused by: java.lang.RuntimeException: Unable to make field private transient volatile java.lang.reflect.Parameter[] java.lang.reflect.Executable.parameters accessible: module java.base does not "opens java.lang.reflect" to unnamed module @192d43ce
    
  • 原因:根据查询的资料,大致意思如下:

    异常是由Java 9及以上版本中引入的Java Platform Module System引起的,特别是强封装的实现。它仅在特定条件下允许access,最突出的条件是:
      - 类型必须是公共的
      - 必须导出拥有的软件包
    对于反射,导致异常的代码尝试使用相同的限制。更确切地说,异常是由对 setAccessible 的调用引起的。	
    为了确保程序成功运行,必须说服模块系统允许访问调用了setAccessible 的元素。
    
  • 可以总结为:从 Java 9 开始,除非明确导出/打开它们,否则并非所有模块都可以访问。由于这是一个运行时问题,可以添加--add-opens为 JVM arg/CLI 选项以使该类型可访问。如果必须允许类路径上的代码进行深度反射以访问非公共成员,请使用 --add-opens 运行时选项。如果还想导出编译时可用的内部类型,可以使用--add-exports,ALL-UNNAMED意味着指定的包在整个代码库中可用。

  • 解决方法:根据报错提示的内容,看需要打开哪个模块就在启动配置 VM Options 中添加,再启动即可。

    如:KocaServerApplication 提示需要打开 “opens java.lang.reflect” 模块,添加如下:

    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
    
    
  • 如需添加多个模块,如:

    --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
    
  • 建议直接在报错信息下搜索 “opens” ,查看需要打开哪些模块就在启动类的 VM Options 中添加即可

  • 常用的模块如下:

    --add-opens=java.base/java.lang=ALL-UNNAMED
    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
    --add-opens=java.base/java.security=ALL-UNNAMED
    --add-opens=java.base/java.util=ALL-UNNAMED
    --add-opens=java.base/java.io=ALL-UNNAMED
    
  • 参考资料:

    module java.base does not "opens java.lang" to unnamed module - 滔天蟹 - 博客园

    Dashboard can not start: java.lang.reflect.InaccessibleObjectException | 控制台本地启动不了 · Issue #2439 · alibaba/Sentinel · GitHub

    Java 16 and 17 compatibility

    https://github.com/pinterest/ktlint/issues/1391

    https://github.com/sshahine/JFoenix/issues/1200

    https://dev.to/jjbrt/how-to-avoid-resorting-to-add-exports-and-add-opens-in-jdk-16-and-later-j3m

1 个赞