JDK13的新特性之AppCDS详解
作者:flydean 发布时间:2023-03-19 10:32:38
简介
AppCDS的全称是Application Class-Data Sharing。主要是用来在不同的JVM中共享Class-Data信息,从而提升应用程序的启动速度。
通常来说,如果要执行class字节码,JVM需要执行下面的一些步骤:给定一个类的名字,JVM需要从磁盘上面找到这个文件,加载,并验证字节码,最后将它加载进来。
如果JVM启动的时候需要加载成百上千个class,那么需要的就不是一个小数目了。
对于打包好的jar包来说,只要jar的内容不变,那么jar包中的类的数据始终是相同的。JVM在启动时候每次都会运行相同的加载步骤。
AppCDS的作用就是将这些能够共享的数据归类成一个存储文件,在不同的JVM中共享。
基本步骤
对AppCDS有了基本的了解之后,我们讲一下AppCDS的大概工作流程:
选择要归档的class,并创建一个class的列表,用在归档中。( -XX:DumpLoadedClassList)
创建归档文件(-Xshare:dump和-XX:SharedArchiveFile)
使用归档文件(-Xshare:on 和 -XX:SharedArchiveFile)
新的JVM可以使用归档文件来启动,从而减少了class加载的步骤。同时加载到内存中的区域甚至可以在其他的JVM实例中共享。从而极大的提高了JVM的启动速度。
下面我们从JDK class文件归档和应用程序class文件归档两个方面来讲解AppCDS的具体使用。
JDK class文件归档
最简单的AppCDS的例子就是归档JDK的class文件。JDK12,JDK13默认情况下已经开启了AppCDS的支持。如果需要停用,我们可以添加 -Xshare:off。
下面的例子专门用于JDK10和JDK11。
创建JDK class-data archive
我们可以使用-Xshare:dump来创建JVM启动时候默认加载的Class-Data:
java -Xshare:dump -XX:SharedArchiveFile=/tmp/sharedarchive.jsa
上面我们添加了参数-XX:SharedArchiveFile,为默认情况下java shared archive file文件会创建在JAVA_HOME/lib/server/下面,这个是需要root权限才能写入的。为了方便起见,我们手动指定了一个有读写权限的目录。
生成的文件大概有12M,接下来我们就可以使用这个JSA文件来启动java程序了。
使用JDK class-data archive启动应用程序
我们先写一个可以运行的CDS hello world:
public class CDSHelloWorld {
public static void main(String[] args) {
System.out.println("CDS Hello World");
}
}
编译之后,我们运行下面的命令来使用上面创建的jsa文件:
java -Xlog:class+load:file=/tmp/sharedarchive.log -XX:SharedArchiveFile=/tmp/sharedarchive.jsa --enable-preview CDSHelloWorld
上面的命令添加了两个运行时参数:
-XX:SharedArchiveFile表示使用哪个具体的jsa文件来运行java程序。
-Xlog:class+load:file主要是做调试用的,将会把JVM的class load信息输出到指定的文件中,方便我们查看。这个unified logging特性是在JDK9中添加的,后面我们也会详细介绍。
简单查看一下生产的log文件:
[0.010s][info][class,load] opened: /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home/lib/modules
[0.017s][info][class,load] java.lang.Object source: shared objects file
[0.017s][info][class,load] java.io.Serializable source: shared objects file
[0.017s][info][class,load] java.lang.Comparable source: shared objects file
...
[0.056s][info][class,load] CDSHelloWorld source: file:/Users/learn-java-base-9-to-14/java-13/target/classes/
从生成的日志文件我们可以看到,除了自己写的java文件,其他的java class都是从shared objects file中加载的。
运行时间对比
我们可以简单的使用time命令来对两种情况进行一下对比,看具体的运行时间差别:
time java -Xlog:class+load:file=/tmp/sharedarchive.log -XX:SharedArchiveFile=/tmp/sharedarchive.jsa --enable-preview CDSHelloWorld
CDS Hello World
java -Xlog:class+load:file=/tmp/sharedarchive.log --enable-preview
0.06s user
0.06s system
77% cpu
0.164 total
time java --enable-preview CDSHelloWorld
CDS Hello World
java --enable-preview CDSHelloWorld
0.09s user
0.06s system
66% cpu
0.222 total
HelloWorld只是一个简单的例子,可能两者的区别还不是特别明显。
如果是大型的项目,处理JDK自带的class之外,我们还可以将项目中共享的模块做成jsa文件,从而提升启动速度。
应用程序class文件归档
应用程序class文件归档和上面讲的JDK class文件归档很类似。基本步骤就是:1.列出运行应用程序时需要加载的class文件。2.将这class文件归档。
在JDK13之前,我们需要两步才能生成jsa文件。在JDK13之后,只需要一个命令就行了。
生成应用程序加载class的列表
我们可以使用XX:DumpLoadedClassList来生成应用程序加载class的列表:
java -XX:DumpLoadedClassList=/tmp/classes.lst --enable-preview CDSHelloWorld
我们可以得到类似下面的class文件列表:
java/lang/Object
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/constant/Constable
java/lang/constant/ConstantDesc
使用class文件列表生成jsa文件
有了class文件列表,我们就可以生成jsa文件了:
java -Xshare:dump -XX:SharedArchiveFile=/tmp/sharedarchive.jsa -XX:SharedClassListFile=/tmp/classes.lst
--enable-preview CDSHelloWorld
跟之前的例子一样,只不过多了一个-XX:SharedClassListFile参数。
JDK13的新用法
在JDK13,一切都变得简单了,只需要一个-XX:ArchiveClassesAtExit就好:
java -XX:ArchiveClassesAtExit=/tmp/sharedarchive.jsa --enable-preview CDSHelloWorld
JVM将会在退出时生成jsa文件。
总结
AppCDS是一个新特性,在特别关注java启动时间的情况下可以考虑使用。
本文的例子https://github.com/ddean2009/learn-java-base-9-to-20
来源:https://segmentfault.com/a/1190000022613537


猜你喜欢
- 本文实例讲述了Android实现的简单蓝牙程序。分享给大家供大家参考,具体如下:我将在这篇文章中介绍了的Android蓝牙程序。这个程序就是
- 这几天面试中有遇到关于main数组中的args数组传值的问题,一般是从命令提示符中传值,也可以直接在java代码中赋值。而且这个数组的长度是
- 一.SQLite的介绍1.SQLite简介SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 
- 前言最近想体验下最新版本的SpringBoot,逛了下官网,发现SpringBoot目前最新版本已经是2.6.4了,版本更新确实够快的。之前
- 本文实例讲述了C++判断一个链表是否为回文结构的方法。分享给大家供大家参考,具体如下:题目:给定一个链表头节点head,请判断是否为回文结构
- 前言:封装、继承和多态是面向对象编程的三大特征。1.封装1.1.封装概念封装就是把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据
- 前言apollo配置经常使用的方式是@value,比较便捷,如果只出现在一个类中还行,但是如果多个类中并不是很方便,特别是如果出现配置值变化
- 话不多说,请看下面//C# 代码int year = DateTime.Now.Year;int month = DateTime.Now.
- C++ boost::asio编程-异步TCP大家好,我是异步方式和同步方式不同,我从来不花时间去等那些龟速的IO操作,我只是向系统说一声要
- System.out.print("\b") 会在控制台下往回删掉一个字符,如果你想回删多个字符就打印多个 "
- 1. 安装JDK解释: JDK是Java编写环境--开发环境注: 安装路径不可出现中文及标点符号。比如:D:\Java\jdk81.1 下载
- 1.ACSII码加密//ACSII码加密 private static string
- 项目中看到了有埋点监控、报表、日志分析,有点兴趣想慢慢捣鼓一下1. 数据埋点监控机器环境的性能和业务流程或逻辑等各项数据,并根据这些数据生成
- 本文实例为大家分享了UnityShader使用Plane实现翻书效果的具体代码,供大家参考,具体内容如下之前在网上看到一个Shadr可以实现
- NDK部分1、下载ndk这里就一笔带过了。2、解压ndk不要解压,文件权限会出错。执行之,会自动解压,然后mv到想放的地方。我放到了”/us
- 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的
- 引言HDFS Balancer工具可以用来分析块的分布情况,并且可以重新分配DataNode中的数据。本文通过为您介绍如何使用HDFS Ba
- 关于静态类型检查和动态类型检查的解释:静态类型检查:基于程序的源代码来验证类型安全的过程;动态类型检查:在程序运行期间验证类型安全的过程;J
- 前言RecyclerView是我们常用的列表控件,一般来说当Item的数据改变的时候我们需要刷新当前的Item 。如何刷新 RV 的列表?基
- 接着上篇java验证码制作(上篇)给大家介绍有关java验证码的相关知识!方法三:用开源组件Jcaptcha实现,与Spring组合使用可产