1 背景
jdk 5 中引入的 class-data sharing (cds) 技术允许将一组类预处理为共享存档文件,然后可以在运行时进行内存映射以减少启动时间。当多个 jvm 共享同一个归档文件时,它还可以减少内存占用。
在 openjdk 社区,cds 技术发展有两个演进方向:
扩大archive的类的范围:cds -> appcds -> dynamic cds。
扩大archive的数据种类:metadata(cds、appcds、dynamic appcds) -> 基本类对象 -> strings -> module -> support for pre-generated java.lang.invoke classes in cds archive。
dynamic cds特性(jep 350: dynamic cds archives[1])主要功能:
继续增加类共享的范围,提升共享类技术的收益
简化使用 appcds 时 dump classlist 的操作,直接在程序退出时 dump 内存中的类到 jsa 文件。
毕昇jdk 8 中实现的 dynamic cds 特性相比之前的 appcds ,增加了 custom classloader 的支持,扩展了共享类的支持范围;且该jdk版本带有基本类的 base jsa 文件,可以消除 dump classlist 的步骤,提高该特性的易用性。经测试,在使用此特性的情况下 springboot 启动时间具有显著提升。
注:jep 350 中 dynamic cds 增加支持的类(lambda、匿名类),毕昇jdk 8 暂时没有实现。
2 特性介绍
java 应用程序使用base jsa运行,在程序执行结束时对类进行动态归档生成top jsa,top jsa将包含base jsa以外所有可以共享的类(包含custom classloader加载的类),共享类范围的扩大提供了更短的启动时间,而且dynamic cds对于额外共享的类采用重定位(relocate)到一个更加紧凑的内存空间以减少空间的浪费。
base jsa:使用cds/appcds生成的类共享文件,当不指定其路径时,默认为:$java_home/jre/lib//server/classes.jsa。
top jsa:使用dynamic cds生成的类共享文件。
注:类数据区分为读写、只读,分别放置在rw、ro区。
此特性可以使用default jsa(jdk包中自带的基本类的jsa文件)作为base jsa,因此可以简化cds特性使用步骤,生成top jsa后,运行程序时则同时将base jsa、top jsa映射到内存中以加速启动和节省内存。
此特性为保证customer classloader加载类的正确性,与appclassloader、extclassloader在findloadedclass时直接由classloader来查找共享类不同,其在defineclass中的基本校验完毕后查询共享类。
3 使用说明
3.1 相关参数说明
分类 选项 含义
运行时选项 -xshare:on 该参数继承 cds,使用共享文件
-xx:+unlockexperimentalvmoptions 开启实验特性
-xx:sharedarchivefile 用于用户首次启动时指定 base jsa 文件,其是生成 top jsa 的基础
-xx:archiveclassesatexit 用户指定进程退出时生成 top jsa 文件路径。文件名支持按照进程号 %p 输出,可避免多jvm进程复写一份 top jsa,导致 top jsa 不可用
日志开关 -xx:infodynamiccds 打开级别为 info 的日志,可以通过 -xx:dynamiccdslog=path 设置输出路径,默认为标准输出流
-xx:debugdynamiccds 打开级别为 debug 的日志,其余同上
-xx:tracedynamiccds 打开级别为 trace 的日志,其余同上
3.2 使用步骤
分为两个步骤:
将可共享类的元数据(metadata)dump 进文件;
使用该文件执行 java 程序。
下面以 helloworld 程序为例简单说明 dynamic cds 的用法。
预置条件:java 程序 helloworld.class。
下面是每个步骤的命令行,相关参数说明请参见 jvm 参数说明。
步骤一:生成 top jsa(依赖 base jsa ),实验特性开关需要使能
java -xx:+unlockexperimentalvmoptions -xshare:on -xx:archiveclassesatexit=top.jsa -xx:+infodynamiccds helloworld
如果因为某些参数改变,导致 jdk 包中带的 default jsa 无法使用,请重新用 cds/appcds 生成 base jsa。
非正常结束的进程,比如 kill -9 杀死进程,则无法生成 jsa,则需要通过 jcmd gc.dynamic_cds_dump 命令在进程结束之前生成。
可省略 -xx:sharedarchivefile 参数,此时默认使用 -xx:sharedarchivefile=$java_home/jre/lib//server/classes.jsa 文件。
因为生成 jsa 过程中会修改运行时数据,无法保证运行时正确,因此 dump top jsa 结束后直接退出进程。
步骤二:使用 top jsa 运行 java 程序
java -xx:+unlockexperimentalvmoptions -xshare:on -xx:archiveclassesatexit=top.jsa -xx:+infodynamiccds helloworld
top jsa 中记录了 base jsa 的路径,可以在参数中只指明 top jsa 。如果 base jsa 路径在 top jsa 生成之后发生了改变,需要同时指明 base、top jsa 的路径:
java -xshare:on -xx:sharedarchivefile=base.jsa:top.jsa -xx:+infodynamiccds helloworld
3.3 使用限制
生成、使用jsa两阶段参数和环境page_size必须一致
restore阶段使用参数 -xx:objectalignmentinbytes=32、16 时,运行时会报错,信息如下:
error occurred during initialization of vmunable to use shared archive.an error has occurred while processing the shared archive file.the shared archive file's objectalignmentinbytes of 8 does not equal the current objectalignmentinbytes of 32.
错误原因:因为生成 base jsa 时,objectalignmentinbytes 默认为8,读取时不支持指定其他对齐参数。
解决方法:重新使用 cds/appcds 生成 base jsa 使用,生成时参数加入使用时对应的 -xx:objectalignmentinbytes 的值即可。
当dump时的系统环境变量pagesize小于使用时的pagesize,运行时会报错,信息如下:
an error has occurred while processing the shared archive file.unable to map readonly shared space at required address.error occurred during initialization of vmunable to use shared archive.
错误原因:page_size 影响 jsa 文件中的数据对齐,系统无法为jsa文件恢复分配内存。
解决方法:重新使用 cds/appcds 在当前环境生成 jsa 使用即可。
不支持关闭压缩指针
使用 cds(restore)阶段使用参数 -xx:-usecompressedoops 或 -xx:-usecompressedclasspointers 时,运行时会报错,信息如下:
error occurred during initialization of vmunable to use shared archive.: usecompressedoops and usecompressedclasspointers must be on for usesharedspaces.class data sharing is inconsistent with other specified options.
错误原因:目前 cds 只支持压缩指针场景。
解决方法:使用时应当开启压缩指针开关,后续会支持压缩指针关闭场景。
最大堆地址值需小于32g(当使用默认参数 -xx:objectalignmentinbytes=8)
使用 cds(restore)阶段使用参数和 (值 )的组合,运行时会报错,信息如下:
an error has occurred while processing the shared archive file.unable to reserve shared space at required address 0x0000000800000000error occurred during initialization of vmunable to use shared archive.
错误原因:jsa 文件的映射地址的堆区间,不能被参数所指定的jvm 其他组件占用。
解决方法:将此组合值 改为小于 32 可正常运行。
dynamic cds 不支持的共享类
java version1.5 以及之前的类不支持共享。
jvm anonymous class 不支持共享。
如果基类不支持共享,则该类也不支持共享。
dynamic cds 不支持 jfr
jfr组件启动过程会通过 asm 动态创建匿名类(anonymous class),与 dynamic cds 冲突。
4 性能测试
springboot场景测试结果:
测试说明:
经测试,使能 dynamic cds 特性相比于默认参数 java -jar spring-petclinic-2.5.0-snapshot.jar 启动效率会提升14.3%。
5 特性演进
后续毕昇jdk8 cds特性将支持压缩指针关闭场景。
iphone8什么时候上市?iphone8最新消息:iphone8会惯性跳票?有理有据这次它的理由很充分
PSpice仿真教程之蒙特卡洛分析
科学团队研发用于监测养鱼场的水下机器人
从三个方面解析光耦参数
精密低功耗信号链:到交流电还是不到交流电
毕昇JDK 8 Dynamic CDS特性介绍
华为:一种5G卫星通信系统架构
选择理想TVS二极管的考虑因素主要有哪几点
安捷伦电子测量事业部正式启用新公司名称-Keysight Technologies(是德科技)
不可思议的人工智能 AI也能搞艺术了
AMD新一代锐龙3笔记本电脑CPU一季度可能会供应不足
复旦微MCU|TSI Tuner 软件说明
锂离子电池应用与特性以及充电方式和设计充电器实例
为何IBIS建模对设计成功至关重要
PlayStation5今年不会发布,预计将在2020年下半正式问世
简单电路将+5V转换为-10V
iPhone 8降价卖断货?春风吹又生?
外媒:台积电挺直“腰板”了
统信软件UOS操作系统装机量突破100万
Honor Smart Screen X1将推出75英寸版本