JDK13的新特性之AppCDS詳解
簡介
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
到此這篇關於JDK13的新特性:AppCDS詳解的文章就介紹到這了,更多相關JDK13的新特性:AppCDS詳解內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!