共计 7909 个字符,预计需要花费 20 分钟才能阅读完成。
download:Python 全能工程师 2022 版完结
Java 17 升级指南
分为几个部分:
编译相干
参数迁徙相干
运行相干
编译相干
JEP 320
在 Java11 中引入了一个提案 JEP 320: Remove the Java EE and CORBA Modules
移除了 Java EE and CORBA 的模块,如果我的项目中用到需要手动引入。比如代码中用到了 javax.annotation.* 下的包:
import javax.annotation.PreDestroy;
public abstract class FridayAgent
@PreDestroy
public void destroy() {agentClient.close();
}
}
在编译时会找不到相干的类。这是因为 Java EE 已经在 Java 9 中被标记为 deprecated,Java 11 中被正式移除,可能手动引入 javax 的包:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
使用了 sun.misc.* 下的包
比如 sun.misc.BASE64Encoder,这个简略,替换一下工具类即可。
[ERROR] symbol: class BASE64Encoder
[ERROR] location: package sun.misc
netty 低版本使用了 sun.misc.*,编译错误信息如下
Caused by: java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0
at io.netty.util.internal.PlatformDependent.getSystemClassLoader(PlatformDependent.java:694) ~[netty-all-4.0.42.Final.jar!/:4.0.42.Final]
对应的源码如下:
/**
- The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}.
*/
final class PlatformDependent0 {
}
https://github.com/netty/nett…
lombok 使用了 com.sun.tools.javac.* 下的包
错误信息如下:
Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.2:compile (default-compile) on project encloud-common: Fatal error compiling: java.lang.ExceptionInInitializerError: Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not “opens com.sun.tools.javac.processing” to unnamed module
如果你的我的项目中使用 lombok,而且是低版本的话,就会出现,lombok 的原理是在编译期做一些手脚,用到了 com.sun.tools.javac 下的文件,升级到最新版可能解决。ps,集体很不喜爱 lombok,调试的时候代码和 class 对不上真的很恶心。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!– <version>1.16.4</version>–>
<version>1.18.24</version>
</dependency>
kotlin 版本限度
咱们后端在很多年前就 all-in Kotlin,Kotlin 的升级也是咱们的重中之重。
[ERROR] Failed to execute goal org.jetbrains.kotlin:kotlin-maven-plugin:1.2.71:compile (compile) on project encloud-core: Compilation failure
[ERROR] Unknown JVM target version: 17
[ERROR] Supported versions: 1.6, 1.8
Kotlin 在 1.6.0 版本开始反对 Java17 的字节码,低于 1.6.0 的编译会间接报错
废除依赖分析
可能用 jdeps –jdk-internals –multi-release 17 –class-path . encloud-api.jar 来做我的项目的依赖分析
这样你就可能知道哪些库需要做升级了。
参数迁徙
什么是 Unified Logging
在 Java 领域,有广为人知的日志框架,slf4j、log4j 等,这些框架提供了对立的编程接口,让用户可能通过简略的配置实现日志输入的个性化配置,比如日志 tag、级别(info、debug 等)、上下文(线程 id、行号、工夫等),在 JVM 外部之前一直不足这样的规范,于是进去了 Unified Logging,实现了日志格局的大一统,这就是咱们接下来要介绍的重点 Unified Logging。
咱们接触最多的是 gc 的日志,在 java8 中,咱们配置 gc 日志的参数是 -Xloggc:/tmp/gc.log。在 JVM 中除了 GC,还有大量的其它相干的日志,比如线程、os 等,在新的 Unified Logging 日志中,日志输入的形式变更为了 java -Xlog:xxx,GC 不再非凡只是做为日志的一种存在形式。
java -Xlog -version
输入后果如下:
可能看到日志输入里,不只有 GC 相干的日志,还有 os 线程相干的信息。事实上 java 的日志的消费者有非常多部分,比如 thread、class load、unload、safepoint、cds 等。
归根到底,日志打印,需要回答明显三个问题:
what:要输入什么信息(tag),以什么日志级别输入(level)
where:输入到哪里(console 还是 file)
decorators:日志如何
输入什么信息(selectors)
首先来看 what 的部分,如何指定要输入哪些信息,这个在 JVM 外部被称之为 selectors。
JVM 采纳的是 <tag-set>=<level> 的形式来示意 selectors,默认情况下,tag 为 all,示意所有的 tag,level 为 INFO,java -Xlog -version 等价于上面的形式
java -Xlog:all=info -version
如果咱们想输入 tag 为 gc,日志级别为 debug 的日志,可能用 java -Xlog:gc=debug 的形式:
$ java -Xlog:gc=debug -version
0.023s[gc] Using G1
0.023s[gc] ConcGCThreads: 3 offset 22
0.023s[gc] ParallelGCThreads: 10
0.024s[gc] Initialize mark stack with 4096 chunks, maximum 524288
这样就输入了 tag 为 gc,级别为 debug 的日志信息。
不过这里有一个比较坑的点是,这里的 tag 匹配规定是精确匹配,如果某条日志的 tag 是 gc,metaspace,通过下面的规定是匹配不到的,咱们可能手动指定的形式来输入。
$ java -Xlog:gc+metaspace -version
0.022s[gc,metaspace] CDS archive(s) mapped at: … size 12443648.
0.022s[gc,metaspace] Compressed class space mapped at: reserved size:…
0.022s[gc,metaspace] Narrow klass base:…, Narrow
klass shift: 0, Narrow klass range: 0x100000000
这里的 selector 也是可能进行组合的,不同的 selector 之间用逗号分隔即可。比如同时输入 gc 和 gc+metaspace 这两类 tag 的日志,就可能这么写:
$ java -Xlog:gc=debug,gc+metaspace -version
0.020s[gc] Using G1
0.020s[gc] ConcGCThreads: 3 offset 22
0.020s[gc] ParallelGCThreads: 10
0.020s[gc] Initialize mark stack with 4096 chunks, maximum 524288
0.022s[gc,metaspace] CDS archive(s) mapped at:
0.022s[gc,metaspace] Compressed class space mapped at:
0.022s[gc,metaspace] Narrow klass base: 0x0000000800000000
当然这么搞是很麻烦的,JVM 提供了通配符 * 来解决精确匹配的问题,比如咱们想要所有 tag 为 gc 的日志,可能这么写:
$ java -Xlog:gc*=debug -version
0.024s[gc,heap] Minimum heap 8388608
0.024s[gc] Using G1
0.024s[gc,heap,coops] Heap address: 0x0000000707400000
0.024s[gc] ConcGCThreads: 3 offset 22
0.024s[gc] ParallelGCThreads: 10
0.024s[gc] Initialize mark stack with 4096 chunks
0.024s[gc,ergo,heap] Expand the heap. requested expansion amount:
0.025s[gc,heap,region] Activate regions [0, 125)
0.025s[gc,ihop] Target occupancy update: old: 0B, new: 262144000B
0.025s[gc,ergo,refine] Initial Refinement Zones: green: 2560
0.026s[gc,task] G1 Service Thread
0.026s[gc,task] G1 Service Thread (Periodic GC Task) (register)
0.026s[gc,init] Version: 17.0.3+7 (release)
…
如果只想要 INFO 级别的日志,则可能省略 level 的设置,使用 java -Xlog:gc* -version 即可。
如果想知道有哪些个性化的 tag 可能抉择,可能用 java -Xlog:help 来找到所有可用的 tag。
阶段性小结
第二部分:输入到哪里(output)
默认情况下,日志会输入到 stdout,jvm 反对以下三种输入形式:
stdout
stderr
file
一般而言咱们会把日志输入到文件中,便利后续进一步分析
-Xlog:all=debug:file=/path_to_logs/app.log
还可能指定日志切割的大小和形式
-Xlog:gc*:file=/path_to_logs/app.log:filesize=104857600,filecount=5
第三部分:日志 decorators
每条日志除了失常的信息以外,还有不少日志相干的上下文信息,在 jvm 中被称为 decorators,有上面这些可选项。
OptionDescriptiontimeCurrent time and date in ISO-8601 format.uptimeTime since the start of the JVM in seconds and milliseconds (e.g., 6.567s).timemillisThe same value as generated by System.currentTimeMillis().uptimemillisMilliseconds since the JVM started.timenanosThe same value as generated by System.nanoTime().uptimenanosNanoseconds since the JVM started.pidThe process identifier.tidThe thread identifier.levelThe level associated with the log message.tagsThe tag-set associated with the log message.
比如可能用 java -Xlog:all=debug:stdout:level,tags,time,uptime,pid -version 选项来打印日志。
2022-06-15T19:54:01.529+08005235[os,thread] Thread attached
2022-06-15T19:54:01.529+08005235[os,thread] Thread 5237 stack…
2022-06-15T19:54:01.529+08005235[perf,datacreation]
Unified Logging 小结
输入格局如下:
-Xlog:[selectors]:[output]:decorators
selectors 是多个 tag 和 level 的组合,起到了 what(过滤器)的作用,格局为 tag1+tag2…=level
decorators 是日志相干的描述信息,也可能理解为上下文
output 是输入相干的选项,一般咱们会配置为输入到文件,按文件大小切割
这里补充一个学识点,就是默认值:
tag:all
level:info
output:stdout
decorators: uptime, level, tags
GC 参数迁徙
可能看到 GC 相干的参数都已经收拢到 Xlog 下,以前的很多 Java8 下的参数已经被移除或者标记为过期。
比如 PrintGCDetails 已经被 -Xlog:gc* 取代:
java -XX:+PrintGCDetails -version
0.001s[gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
常见的标记为废除的参数还有 -XX:+PrintGC 和 -Xloggc:<filepath>,迁徙前后的参数如下:
旧参数新参数 -XX:+PrintGCDetails-Xlog:gc*-XX:+PrintGC-Xlog:gc-Xloggc:<filepath>-Xlog:gc:file=<filepath>
除此之外,大量的 GC 的参数被移除,比如罕用的参数 -XX:+PrintTenuringDistribution,Java17 会拒绝启动
java -XX:+PrintTenuringDistribution -version
Unrecognized VM option ‘PrintTenuringDistribution’
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
更粗疏的移除的参数如下
CMSDumpAtPromotionFailure,
CMSPrintEdenSurvivorChunks,
GlLogLevel,
G1PrintHeapRegions,
G1PrintRegionLivenessInfo,
G1SummarizeConcMark,
G1SummarizeRSetStats,
G1TraceConcRefinement,
G1TraceEagerReclaimHumongousObjects,
G1TraceStringSymbolTableScrubbing,
GCLogFileSize, NumberofGCLogFiles,
PrintAdaptiveSizePolicy,
PrintclassHistogramAfterFullGC,
PrintClassHistogramBeforeFullGC,
PrintCMSInitiationStatistics
PrintCMSStatistics,
PrintFLSCensus,
PrintFLSStatistics,
PrintGCApplicationConcurrentTime
PrintGCApplicationStoppedTime,
PrintGCCause,
PrintGCDateStamps,
PrintGCID,
PrintGCTaskTimeStamps,
PrintGCTimeStamps,
PrintHeapAtGC,
PrintHeapAtGCExtended,
PrintJNIGCStalls,
PrintOldPLAB
PrintParallel0ldGCPhaseTimes,
PrintPLAB,
PrintPromotionFailure,
PrintReferenceGC,
PrintStringDeduplicationStatistics,
PrintTaskqueue,
PrintTenuringDistribution,
PrintTerminationStats,
PrintTLAB,
TraceDynamicGCThreads,
TraceMetadataHumongousAllocation,
UseGCLogFileRotation,
VerifySilently
这些移除的参数大部分都能在新的日志体系下找到对应的参数,比如 PrintHeapAtGC 这个参数可能用 -Xlog:gc+heap=debug 来代替
$ java -Xlog:gc+heap=debug -cp . G1GCDemo01
0.004s[gc,heap] Minimum heap 8388608 Initial heap 268435456 Maximum heap
hello, g1gc!
12.263s[gc,heap] GC(0) Heap before GC invocations=0 (full 0):
12.265s[gc,heap] GC(0) garbage-first heap
12.265s[gc,heap] GC(0) region size 2048K, 1 young (2048K)
12.265s[gc,heap] GC(0) Metaspace used 3678K
12.265s[gc,heap] GC(0) class space used 300K
12.280s[gc,heap] GC(0) Uncommittable regions after shrink: 124