JEP 350:动态 CDS 档案
概括
扩展应用程序类数据共享,以允许在 Java 应用程序执行结束时动态归档类。归档的类将包括默认的基础层 CDS 归档中不存在的所有加载的应用程序类和库类。
目标
-
提高应用程序类数据共享( AppCDS )的可用性。用户无 需进行试运行即可为每个应用程序创建类别列表。
-
通过该选项启用的静态归档
-Xshare:dump
(使用类列表)应该可以继续工作。这包括内置类加载器和用户定义的类加载器的类。
非目标
-
只有在应用程序执行期间加载的类才会被存档。存在于给定 JAR 文件中但在执行期间未加载的类将不会被归档。
-
应用程序执行期间创建的 Java 堆对象不会被动态归档。
-
如果应用程序突然退出(例如崩溃),则不会进行动态归档。
动机
相对于默认的 CDS 存档,在 HotSpot 中使用 AppCDS 存档应用程序类可提供额外的启动时间和内存优势。但是,目前要将 AppCDS 用于 Java 应用程序需要三个步骤:
- 进行一次或多次试运行以创建班级列表
- 使用创建的类列表转储存档
- 使用存档运行
此外,此过程仅适用于仅使用内置类加载器的应用程序。 HotSpot 中对归档由用户定义的类加载器加载的类有实验性支持,但使用起来并不方便。
由命令行选项启用的动态归档将通过消除试运行(上面的步骤 1)来简化 AppCDS 的使用,并将有效且统一地支持内置类加载器和用户定义的类加载器。
该 JEP 的后续增强功能可以在应用程序首次运行期间自动生成存档。这将消除显式存档创建步骤(上面的步骤 2)。 CDS/AppCDS 的使 用可以完全透明且自动。
描述
支持的存档配置
运行时将支持以下配置:
- 静态基础存档(默认 CDS 存档)+ 动态存档 — 当两个存档都成功映射时
- 仅静态基础存档 - 当动态存档无法映射时
动态存档当前需要使用默认 CDS 存档作为基础存档。如果在运行时无法映射和使用基础层存档,则顶层动态存档将自动禁用。
在退出时归档课程
-XX:ArchiveClassesAtExit
如果指定了该选项,则应用程序退出时会动态创建共享存档。
动态生成的存档是在与运行的 JDK 映像一起打包的默认系统存档之上创建的。为每个应用程序生成一个单独的顶层归档文件。用户可以指定动态存档名称的文件名作为选项的参数-XX:ArchiveClassesAtExit
。例如,以下命令创建hello.jsa
:
% bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
要使用此动态存档运行同一应用程序:
% bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
基础层依赖
动态创建的顶层档案 依赖于基础层档案(即,它包含指向基础层数据的指针),因此基础档案头和所有共享空间的CRC值都记录在顶层中。
在运行时,当映射动态归档时,所有记录的 CRC 值都会与当前映射的基本归档 CRC 值进行比较。如果任何 CRC 值不匹配,则动态存档将被禁用,而不会影响当前映射的基础存档的使用。
使用 CRC 值检查基础归档依赖性比使用文件名、大小和时间戳检查更可靠。
复制和重新定位类元数据
所有加载的应用程序类和库类(不包括基础层中的类)都动态归档在顶层。目前,复制和重新定位类元数据是在应用程序执行结束和虚拟机退出之前完成的。归档数据将被清理,以删除任何不可共享的信息。
对于用户定义的类加载器,JVM 需要在类加载器及其加载的类被卸载之前进行额外的复制。缓冲的数据与其余动态归档的类元数据一起复制到共享空间中。
动态档案中的共享空间
动态存档的布局与现有的静态存档类似。元数据分为以下四个空间。不需要“md”空间。
- rw : 可读/可写数据
- ro:只读数据
- mc : 蹦床
共享空间在运行时单独映射。 “ro”空间被映射为只读以启用跨进程共享。
节省内存
当同一主 机上运行多个相关进程时,可以通过使用两级归档来改进内存共享。例如,当您有这些共享同一组库的程序时:
2 个进程使用“-cp:lib.jar:foo.jar FooApp”运行
4 个进程使用“-cp:lib.jar:bar.jar BarApp”运行
您可以仅为 lib.jar 中的类(以及这些应用程序使用的其他系统类)创建静态存档(使用类列表)。然后,创建两个不同的动态档案,一个用于“foo”应用程序,另一个用于“bar”应用程序。
这样,静态档案可以在所有 6 个进程之间共享,动态档案可以在运行同一程序的进程之间共享。
备择方案
在动态归档期间复制和重新定位类元数据可以在加载请求的类后立即完成。将类元数据重新定位到归档空间可以在应用程序执行结束时、VM 退出之前通过将数据重新定位到归档空间来完成。
测试
- 应执行所有现有的 CDS 和 AppCDS 测试,以确保类列表中的静态归档有效。
- 应该开发新的测试来测试使用内置类加载器和用户定义的类加载器的动态归档。