跳到主要内容

JEP 350:动态 CDS 存档

QWen Max 中英对照

概述

扩展应用程序类数据共享,以允许在 Java 应用程序执行结束时对类进行动态归档。归档的类将包括所有已加载的应用程序类和不在默认的基础层 CDS 归档中的库类。

目标

  • 提高应用类数据共享(AppCDS)的可用性。消除用户为每个应用程序创建类列表进行试运行的需求。

  • 通过 -Xshare:dump 选项启用的静态归档功能(使用类列表)应继续工作。这包括内置类加载器和用户定义类加载器的类。

非目标

  • 在应用程序执行期间加载的类才会被存档。在给定的 JAR 文件中存在的但未在执行期间加载的类不会被存档。

  • 在应用程序执行期间创建的 Java 堆对象不会被动态存档。

  • 如果应用程序异常退出,例如崩溃,将不会进行动态存档。

动机

在 HotSpot 中使用 AppCDS 归档应用程序类,相对于默认的 CDS 归档,可以提供额外的启动时间和内存优势。然而,目前需要一个三步流程才能在 Java 应用程序中使用 AppCDS:

  1. 进行一次或多次试运行以创建类列表
  2. 使用创建的类列表转储存档
  3. 使用存档运行程序

此外,此过程仅适用于只使用内置类加载器的应用程序。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”空间被映射为只读,以启用跨进程共享。

内存节省

当您在同一主机上运行多个相关进程时,可以通过使用两级存档来改善内存共享。例如,当您有这些共享相同库集的程序时:

使用 -cp:lib.jar:foo.jar FooApp 运行的进程有 2 个。

4 个进程正在运行,使用参数 "-cp:lib.jar:bar.jar BarApp"

你可以创建一个仅包含 lib.jar 中的类(以及这些应用程序使用的其他系统类)的静态归档文件(使用类列表)。然后,为 “foo” 应用程序和 “bar” 应用程序分别创建两个不同的动态归档文件。

这样,静态存档可以由全部 6 个进程共享,动态存档可以在运行相同程序的进程之间共享。

替代方案

在动态归档期间复制和重定位类元数据可以在请求加载类之后立即进行。在应用程序执行结束时、虚拟机退出之前,可以通过将数据重定位到归档空间来完成类元数据向归档空间的重定位。

测试

  • 应执行所有现有的 CDS 和 AppCDS 测试,以确保基于类列表的静态归档功能正常。
  • 应开发新测试,以使用内置类加载器和用户定义的类加载器来测试动态归档。