學習JVM引數前必須瞭解的
JVM引數是什麼
大家照相通常使用手機就夠用了,但是針對發燒友來說會使用更專業的裝置,比如單反相機,在單反裡有好幾個模式,P/A/S/M,其中P是傻瓜模式,程式會自動根據環境設定快門速度和光圈大小,以得到相對合適的曝光效果。A檔是光圈優先,使用者可以自己設定光圈大小,快門速度等都交給相機程式來決定,類似半自動化的模式。S檔是快門優先模式,和A檔類似,只是使用者可以設定快門速度。最後一個模式是M檔,這是純手動模式,由使用者自己來調整快門速度,光圈大小等,這個對人的要求就會很高,但是很多專家往往都會選擇M檔來拍攝自己的作品。
可以把JVM想象成相機,JVM引數想象成光圈大小,快門速度之類的引數值,這些引數對程式的執行會影響挺大。
java程式跑在JVM上,JVM會根據環境自動設定一些JVM引數,但是這些引數並不能保證一定是最優的,有些引數在啟動的時候就基本設定好了,它們在執行的時候還無法調整。為了讓JVM能更好地執行你的程式,還是有必要對JVM引數有一定的理解,知道這些JVM引數分別在什麼場景下有效果,起到什麼作用,比如我們到底期不期望類可以解除安裝,是否可以在執行的時候列印一些日誌協助我們瞭解JVM的執行情況,出問題的時候是否可以自動給我們做一些現場資料的保留等,這些都是可以通過JVM引數來設定的。
JVM引數有多少
相機調整的無非就那麼幾個引數值,那JVM引數到底有多少個呢,大概有1000多個,是不是讓你很震驚,沒錯,確實有這麼多。
大家可以到 JVM引數 | PerfMa應用效能技術社群 去看看所有這些JVM引數(注:這是PerfMa社群專門為大家分享JVM引數經驗的討論區),當然我們不一定非得對每個JVM引數要了解清楚,但是對一些常見的,有助於效能調優的JVM引數還是有必要了解一下的。
JVM引數通常設定的位置
我們啟動一個java程式很簡單,命令類似如下
java Main
我們都知道上面的Main是程式的啟動類,JVM執行的時候會找到這個Main類裡的如下簽名的函式
Public static void main(String args[])
那這裡函式的引數args怎麼傳進來的呢?我們通過在啟動命令的主類後面加上相關的引數,引數之間用空格分開,JVM會自動將這些引數作為args的組成部分傳進來,比如
java Main arg1 arg2
這樣,args這個數組裡自動會填充arg1和arg2兩個元素,這樣在你的程式裡就可以使用這些引數了
我們把arg1和arg2這些叫做程式引數,但是和我們課程相關的並不是程式引數,而是JVM引數,那JVM引數放到哪裡呢?JVM引數都是放在主類之前,java命令之後,比如
java -Xmx100M Main arg1 arg2
這裡的-Xmx100M其實就是JVM引數,所以所有的JVM引數都是放在這個位置的,如果不是這個位置,那你設定的JVM引數將會是無效的,如果引數出現不符合預期的情況,那請第一時間檢查的是你JVM引數設定的位置,當然還可能存在一些別的原因導致JVM引數和你設定的情況可能不一致的情況
JVM引數的寫法
那JVM引數具體怎麼寫呢,可以有好幾種
- “-X” 開頭的,比如-Xmx100M
- “-XX: ” 開頭的,比如-XX:+UseG1GC
- “-” 開頭的,比如-verbose:gc
其中-X
和-
開頭的通常會被轉換為一個或者多個-XX:
開頭的引數,只是一個簡化的寫法,比如說-Xmx100M
,JVM裡會自動轉化為-XX:MaxHeapSize=100M
,-verbose:class
會自動轉換為-XX:+TraceClassLoading -XX:+TraceClassUnloading
通過Flags引數指定JVM引數檔案
如果JVM引數都和原始碼伴著一起釋出的話,如果僅僅修改JVM引數也必須拉個分支提交程式碼,這不是很友好,有什麼好辦法呢?
我們可以在啟動引數裡設定一個引數就好,這個引數類似如下
java -XX:Flags=/home/admin/flags Main arg1 arg2
設定過這個引數之後,我們只要在服務的/home/admin目錄下建立flags檔案,同時在這個檔案裡指定所有的JVM引數就可以了,但是對flags檔案裡的引數寫法會有些要求,-X之類的引數不能設定,但是可以用其等價的-XX的引數來替代,比如說-Xmx100M,只能用-XX:MaxHeapSize=100M來取代,同時在檔案裡不要出現-XX:
,只要key=value
或許+/-key
就可以了,不同的引數之間用換行或者空格分開即可,比如flags檔案的內容如下:
MaxHeapSize=8G +UseG1GC
其實等價於
-Xmx8G -XX:+UseG1GC
可以通過加上-XX:+PrintVMOptions
可以列印設定過的JVM引數來驗證,比如
java -XX:Flags=/home/admin/flags -XX:+PrintVMOptions Main arg1 arg2
通過VMOptionsFile引數來指定JVM引數檔案
使用上面的Flags引數可能會比較彆扭,因為設定引數和我們正常的寫法不太一樣,如果我們的JDK版本大於1.8的話,JVM提供了一個更人性化的引數,那就是VMOptionsFile來取代Flags,這也是指定一個檔案,這個檔案裡的JVM參的寫法和我們在java命令後寫的JVM引數寫法完全一樣
java -XX:VMOptionsFile=/home/admin/flags Main arg1 arg2
在flags檔案裡我們可以這麼寫
-Xmx8G -XX:+UseG1GC
是不是方便了很多呢
開始JVM引數學習之旅
上面這些內容都瞭解清楚之後,就可以開始真正學習JVM引數了,我們也專門在社群給大家開了一門免費的學習JVM引數的課程,有興趣的同學請到PerfMa社群進行了解學習,也歡迎大家參與討論,慢慢揭開JVM引數的神祕面紗。
一起來學習吧:
PerfMa KO 系列之 JVM 引數【Memory