天天看點

JDK13的新特性:AppCDS詳解

AppCDS的全稱是Application Class-Data Sharing。主要是用來在不同的JVM中共享Class-Data資訊,進而提升應用程式的啟動速度。

通常來說,如果要執行class位元組碼,JVM需要執行下面的一些步驟:給定一個類的名字,JVM需要從磁盤上面找到這個檔案,加載,并驗證位元組碼,最後将它加載進來。

如果JVM啟動的時候需要加載成百上千個class,那麼需要的就不是一個小數目了。

對于打包好的jar包來說,隻要jar的内容不變,那麼jar包中的類的資料始終是相同的。JVM在啟動時候每次都會運作相同的加載步驟。

目錄

  • ​​簡介​​
  • ​​基本步驟​​
  • ​​JDK class檔案歸檔​​
  • ​​建立JDK class-data archive​​
  • ​​使用JDK class-data archive啟動應用程式​​
  • ​​運作時間對比​​
  • ​​應用程式class檔案歸檔​​
  • ​​生成應用程式加載class的清單​​
  • ​​使用class檔案清單生成jsa檔案​​
  • ​​JDK13的新用法​​
  • ​​總結​​

JDK13的新特性:AppCDS詳解

簡介

AppCDS的全稱是Application Class-Data Sharing。主要是用來在不同的JVM中共享Class-Data資訊,進而提升應用程式的啟動速度。

通常來說,如果要執行class位元組碼,JVM需要執行下面的一些步驟:給定一個類的名字,JVM需要從磁盤上面找到這個檔案,加載,并驗證位元組碼,最後将它加載進來。

如果JVM啟動的時候需要加載成百上千個class,那麼需要的就不是一個小數目了。

對于打包好的jar包來說,隻要jar的内容不變,那麼jar包中的類的資料始終是相同的。JVM在啟動時候每次都會運作相同的加載步驟。

AppCDS的作用就是将這些能夠共享的資料歸類成一個存儲檔案,在不同的JVM中共享。

基本步驟

對AppCDS有了基本的了解之後,我們講一下AppCDS的大概工作流程:

  1. 選擇要歸檔的class,并建立一個class的清單,用在歸檔中。( -XX:DumpLoadedClassList)
  2. 建立歸檔檔案(-Xshare:dump和-XX:SharedArchiveFile)
  3. 使用歸檔檔案(-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​​

本文作者:flydean程式那些事