写在前面:
JDK8在2020年1月份就要禁止商业了,所以下载了下一个官方长期支持版JDK11,从JDK1.8升级至JDK11尝鲜体验一下,虽然现在大多使用的还是1.7、1.8,但是毕竟未来的升级也是趋势。JDK11采用的是模块化方式以实现强制封装的目的,去除了一些包,有些包需要自己手动引入,我没有采用这种模块化的方式,直接启动没有更改任何代码的情况下,启动报错,大概是这样:
java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled 和
java.lang.IllegalAccessException: class io.netty.util.internal.PlatformDependent0$6 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @328510f7
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
虽然有报错误信息,但是不影响正常的程序,而且在Linux环境下安装JDK11跑项目也没有发现问题,查询各种资料后得知可以通过几种方式解决,1:升级依赖包,2:添加maven ,3:用 module-info.java 的方式遵循新规范,改造项目实现模块化
<compilerArgs>
<arg>-J--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED</arg>
</compilerArgs>
经过尝试,1和2这两种方式均不能解决我现在的问题,还是会有启动错误提示,所谓我决定对项目进行模块化尝试改造,看看是否可行。
环境:
JDK11.0.5 + SpringBoot 2.2.0.RELEASE + Tomcat-9.0.27 + Maven-3.6.2
开始:
- 首先安装JDK11.0.5 在Windows10上配置环境变量,默认安装完成之后是没有jre包的,需要自己手动生成,在安装完成之后的JDK安装目录下执行(CMD方式)
bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre
执行完毕后就可以看到jdk目录下就生成了jre文件包
配置环境变量:JAVA_HOME CLASSPATH PATH 这三项
我配置的为:
- JAVA_HOME:C:\Program Files\Java\jdk-11.0.5
- CLASSPATH :%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
- PATCH:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
其它的Maven配置与SpringBoot就不多说了,进入正题
为了实现模块化,将项目先拆分为不同功能不同业务单独承担各自模块,变为一个父项目多个子模块,项目大概如下:
- 设置IDEA的maven使用JDK与项目使用JDK的版本
File | Settings | Build, Execution, Deployment | Build Tools | Maven | Importing
File | Settings | Build, Execution, Deployment | Build Tools | Maven | Runner
设置java项目编译JDK版本
File | Settings | Build, Execution, Deployment | Compiler | Java Compiler
配置项目统一JDK
Ctrl+Alt+Shift+S 快捷键打开设置
添加JDK版本
设置每一个模块为JDK11
- 父模块与子模块之间的引用
父pom中引用各个子模块(引用的名称取决于创建模块时取的模块名称)
子模块以jre报的形式,pom中药先引入父项目以及要引用的兄弟模块,基本配置如下(例):
每个子模块均用次中方式相互引用,pure-modularity-web 模块是本项目的入口项目,所以打包的时候是在这个模块进行打包配置,所以这个模块的打包方式我配置成了war形式
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.modularity.PureApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
至此,SpringBoot分模块项目拆分完成,使用maven的方式查看是否有错
以此点击测试,最后结果为成功
启动项目,没问题,但还是有那个错误
- 接下来模块化,在每个模块下创建 module-info.java,模块名称可以随便起,例如 pure.modularity.service 模块的
open module com.modularity.service {
requires com.modularity.config;
requires spring.beans;
requires spring.context;
requires java.transaction;
requires com.modularity.base;
requires com.modularity.model;
requires com.modularity.util;
requires org.apache.commons.lang3;
requires org.slf4j;
requires spring.data.commons;
requires spring.tx;
requires java.persistence;
requires fastjson;
requires java.annotation;
requires quartz;
requires spring.context.support;
exports com.modularity.service.User;
exports com.modularity.service.Hzfk;
exports com.modularity.service.Job;
exports com.modularity.service.WebSocket;
requires lombok;
requires org.apache.tomcat.embed.websocket;
requires jdk.unsupported;
requires spring.data.jpa;
}
这里引用的时候进行强制封装,导出和引入都需要显式的写出来,如果不知道依赖了那些,可以通过maven 的 compile 来查看
每个模块都需要创建模块文件 module-info.java 来表示那些要引入,那些要导出被其他模块引用
最后的项目结构大致为:
- 测试项目
还是使用maven clean 与 maven compile 排查错误的依赖,问题都解决后进行打包项目,成功
但是在使用IDEA进行编译的时候出现一个问题
Information:java: compiler message file broken: key=compiler.misc.msg.bug arguments=11.0.5, {1}, {2}, {3}, {4}, {5}, {6}, {7}
Information:java: java.lang.module.ResolutionException: Module lombok does not read a module that exports org.mapstruct.ap.spi
Information:java: at java.base/java.lang.module.Resolver.resolveFail(Resolver.java:885)
Information:java: at java.base/java.lang.module.Resolver.checkExportSuppliers(Resolver.java:760)
Information:java: at java.base/java.lang.module.Resolver.finish(Resolver.java:362)
Information:java: at java.base/java.lang.module.Configuration.<init>(Configuration.java:130)
Information:java: at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:484)
Information:java: at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:288)
Information:java: at jdk.compiler/com.sun.tools.javac.file.JavacFileManager.getServiceLoader(JavacFileManager.java:985)
Information:java: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Information:java: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
Information:java: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Information:java: at java.base/java.lang.reflect.Method.invoke(Method.java:566)
Information:java: at org.jetbrains.jps.javac.JavacMain$2.invoke(JavacMain.java:290)
Information:java: at com.sun.proxy.$Proxy23.getServiceLoader(Unknown Source)
Information:java: at com.sun.proxy.$Proxy24.getServiceLoader(Unknown Source)
Information:java: at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.initProcessorLoader(JavacProcessingEnvironment.java:261)
Information:java: at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.<init>(JavacProcessingEnvironment.java:237)
Information:java: at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.instance(JavacProcessingEnvironment.java:193)
Information:java: at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.initProcessAnnotations(JavaCompiler.java:1136)
Information:java: at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
Information:java: at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
Information:java: at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:147)
Information:java: at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
Information:java: at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
Information:java: at org.jetbrains.jps.javac.JavacMain.compile(JavacMain.java:195)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.compileJava(JavaBuilder.java:460)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.compile(JavaBuilder.java:330)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.doBuild(JavaBuilder.java:255)
Information:java: at org.jetbrains.jps.incremental.java.JavaBuilder.build(JavaBuilder.java:213)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runModuleLevelBuilders(IncProjectBuilder.java:1324)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runBuildersForChunk(IncProjectBuilder.java:1004)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildTargetsChunk(IncProjectBuilder.java:1071)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunkIfAffected(IncProjectBuilder.java:965)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunks(IncProjectBuilder.java:794)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.runBuild(IncProjectBuilder.java:376)
Information:java: at org.jetbrains.jps.incremental.IncProjectBuilder.build(IncProjectBuilder.java:178)
Information:java: at org.jetbrains.jps.cmdline.BuildRunner.runBuild(BuildRunner.java:139)
Information:java: at org.jetbrains.jps.cmdline.BuildSession.runBuild(BuildSession.java:288)
Information:java: at org.jetbrains.jps.cmdline.BuildSession.run(BuildSession.java:121)
Information:java: at org.jetbrains.jps.cmdline.BuildMain$MyMessageHandler.lambda$channelRead0$0(BuildMain.java:228)
Information:java: at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
Information:java: at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
Information:java: at java.base/java.lang.Thread.run(Thread.java:834)
Information:java: Errors occurred while compiling module 'pure-modularity-model'
Information:javac 11.0.5 was used to compile java sources
Information:2019/10/23 12:53 - Build completed with 1 error and 0 warnings in 10 s 554 ms
Error:java: Compilation failed: internal java compiler error
上面说的是编译器损坏,但如果把打包好的war包拿到外部的tomcat进行跑,是没有报这个错的,怀疑是JDK配置不低,于是按照上面说的几处又检查了一遍,发现都配置了,没有什么问题,于是便卡在了这里
总结
模块化分出来后没有任何问题,项目正常启动,但如果每个模块都加上模块化 module-info.java 类后就启动不了项目,编译出错,所以先搁置了,有明白这个问题的大拿请出手指点,如果有一天这个问题解决了,我会回来把文字补全,感谢。