為了執(zhí)行字節(jié)碼秕狰,JVM需要一些準(zhǔn)備的工作。給類名躁染,在磁盤上查找類鸣哀,加載它,驗(yàn)證字節(jié)碼吞彤,將類裝載為自己的內(nèi)部數(shù)據(jù)結(jié)構(gòu)我衬,每一步都需要花費(fèi)一些時(shí)間,想想每次JVM都要加載成千上萬(wàn)個(gè)類饰恕,這時(shí)時(shí)間上的花費(fèi)很明顯可以看得出來(lái)挠羔。
因?yàn)镴ar包并沒(méi)有改變,class-data一直都是相同的埋嵌,每次JVM執(zhí)行的也是相同的查找破加,加載,驗(yàn)證動(dòng)作雹嗦。
AppCDS就是讓類只做一次上述的驗(yàn)證范舀,加載動(dòng)作,然后將其打包了罪,后續(xù)在運(yùn)行相同的jar包時(shí)锭环,直接從打包文件中讀取類數(shù)據(jù),或者當(dāng)前同時(shí)運(yùn)行的JVM實(shí)例直接共享一份相同的類數(shù)據(jù)泊藕。
- 不需要在進(jìn)行復(fù)雜的類加載機(jī)制的每一步
- 多個(gè)JVM實(shí)例同時(shí)運(yùn)行時(shí)辅辩,可以共享內(nèi)存區(qū)
使用方式
使用APPCDS的完整步驟一般如下,不過(guò)現(xiàn)在JDK13簡(jiǎn)化了我們的操作娃圆,一般我不需要進(jìn)行下面的所有步驟汽久。
1 創(chuàng)建一個(gè)class的列表,讓這些class可以被打包踊餐。
-XX:DumpLoadedClassList
2 創(chuàng)建歸檔使用
-Xshare:dump -XX:SharedArchiveFile
3 使用歸檔
-Xshare:on -XX:SharedArchiveFile
歸檔系統(tǒng)類
創(chuàng)建歸檔
在JDK13中景醇,系統(tǒng)內(nèi)置的共享類以及被默認(rèn)創(chuàng)建了,位于${JAVA_HOME}/lib/server
目錄下
# 例如
ls /Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/lib/server
# 列出classes.jsa libjsig.dylib libjvm.dylib
使用歸檔
打印類加載日志吝岭,查看日志文件中的信息三痰,如果出現(xiàn)shared objects files
代表使用了appcds的歸檔文件。
注意:不是所有的類都會(huì)被共享窜管,當(dāng)前我們自定義的類仍然會(huì)走全部的類裝載流程散劫。
# 使用歸檔文件
/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -Xlog:class+load:file=cds.log -XX:SharedArchiveFile=jdk13.jsa -jar target/HelloApp.jar
# 不使用歸檔文件
/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -Xlog:class+load:file=nocds.log -Xshare:off -jar target/HelloApp.jar
時(shí)間對(duì)比
明顯看出來(lái)在使用歸檔之后用戶態(tài)的時(shí)間縮短了一些,這次jar包幕帆,僅僅打印Hello World获搏,沒(méi)有做任何事情,如果在類增多的時(shí)候失乾,效果就非常明細(xì)常熙。
time /Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -XX:SharedArchiveFile=jdk13.jsa -jar target/HelloApp.jar
time /Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -Xshare:off -jar target/HelloApp.jar
歸檔自定義類
其實(shí)JDK13已經(jīng)默認(rèn)幫我們把系統(tǒng)的類文件進(jìn)行歸檔了纬乍,我們?cè)谑褂玫臅r(shí)候也不需要指定什么參數(shù),默認(rèn)-Xshare:on
裸卫。系統(tǒng)類的歸檔我們不需要關(guān)系太多仿贬,那么如何打包我們的應(yīng)用類文件呢。
1 使用-XX:DumpLoadedClassList=classes.lst
查看當(dāng)前JVM裝載的類列表
2 使用-XX:SharedClassListFile=classes.lst
來(lái)指定那些類需要共享墓贿,以及指定-XX:SharedArchiveFile=app-cds.jsa
打包文件位置茧泪,這里不需要使用-jar來(lái)運(yùn)行程序,指定jar包的位置即可聋袋。
/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=jdk13-custom.jsa --class-path target/HelloApp.jar
3 可以在JVM退出的時(shí)候队伟,自動(dòng)歸檔,使用選項(xiàng)-XX:ArchiveClassesAtExit=app-cds.jsa
4 使用歸檔文件
/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/java -XX:SharedArchiveFile=jdk13-custom.jsa -jar target/HelloApp.jar
問(wèn)題
有過(guò)有人更新了jar包的內(nèi)容幽勒,共享類會(huì)怎么處理缰泡?
可以查看日志看一下,是否會(huì)加載修改后的類代嗤。-Xlog:class+load:file=cds.log
如果有任何問(wèn)題棘钞,還是-Xlog:class+load:file=cds.log
看一下情況。
最后
JDK13中使用AppCDS的選項(xiàng)-XX:ArchiveClassesAtExit=${ARCHIVE}
干毅,-XX:SharedArchiveFile=${ARCHIVE}
參考:https://blog.codefx.org/java/application-class-data-sharing/#Launch-Time-Measurements