JVM優化(1)jvm執行引數
1、為什麼要進行JVM優化?
在本地開發環境中我們很少會遇到需要對jvm進行優化的需求,但是到了生產環境,我們
可能將有下面的需求:
- 執行的應用 “卡住了”,日誌不輸出,程式沒有反應
- 伺服器的 CPU負載突然升高
- 在多執行緒應用下,如何分配執行緒的數量?
。。。。。
對jvm優化分析解決在生產環境中所遇到的各種“棘手”的問題。
在jvm中有很多的引數可以進行設定,這樣可以讓jvm在各種環境中都能夠高效的執行。絕大部分的引數保持預設即可。
注:使用的jdk版本為1.8。
2、三種引數型別
jvm的引數型別分為三類,分別是:
標準引數:
- -help
- -version
-X 引數 (非標準引數):
- -Xint
- -Xcomp
-XX 引數(使用率較高):
- -XX:newSize
- -XX:+UseSerialGC
3、標準引數
jvm的標準引數,一般都是很穩定的,在未來的JVM版本中不會改變,可以使用java -help 檢索出所有的標準引數。
[[email protected] ~]# java ‐help 用法: java [‐options] class [args...] (執行類) 或 java [‐options] ‐jar jarfile [args...] (執行 jar 檔案) 其中選項包括: ‐d32 使用 32 位資料模型 (如果可用) ‐d64 使用 64 位資料模型 (如果可用) ‐server 選擇 "server" VM 預設 VM 是 server, 因為您是在伺服器類計算機上執行。 ‐cp <目錄和 zip/jar 檔案的類搜尋路徑> ‐classpath <目錄和 zip/jar 檔案的類搜尋路徑> 用 : 分隔的目錄, JAR 檔案 和 ZIP 檔案列表, 用於搜尋類檔案。 ‐D<名稱>=<值> 設定系統屬性 ‐verbose:[class|gc|jni] 啟用詳細輸出 ‐version 輸出產品版本並退出 ‐version:<值> 警告: 此功能已過時, 將在 未來發行版中刪除。 需要指定的版本才能執行 ‐showversion 輸出產品版本並繼續 ‐jre‐restrict‐search | ‐no‐jre‐restrict‐search 警告: 此功能已過時, 將在 未來發行版中刪除。 在版本搜尋中包括/排除使用者專用 JRE ‐? ‐help 輸出此幫助訊息 ‐X 輸出非標準選項的幫助 ‐ea[:<packagename>...|:<classname>] ‐enableassertions[:<packagename>...|:<classname>] 按指定的粒度啟用斷言 ‐da[:<packagename>...|:<classname>] ‐disableassertions[:<packagename>...|:<classname>] 禁用具有指定粒度的斷言 ‐esa | ‐enablesystemassertions 啟用系統斷言 ‐dsa | ‐disablesystemassertions 禁用系統斷言 ‐agentlib:<libname>[=<選項>] 載入本機代理庫 <libname>, 例如 ‐agentlib:hprof 另請參閱 ‐agentlib:jdwp=help 和 ‐agentlib:hprof=help ‐agentpath:<pathname>[=<選項>] 按完整路徑名載入本機代理庫 ‐javaagent:<jarpath>[=<選項>] 載入 Java 程式語言代理, 請參閱 java.lang.instrument ‐splash:<imagepath> 使用指定的影象顯示啟動螢幕
3.1、實戰
實戰1:檢視jvm版本
[[email protected] ~]# java ‐version java version "1.8.0_141" Java(TM) SE Runtime Environment (build 1.8.0_141‐b15) Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode) # ‐showversion引數是表示,先列印版本資訊,再執行後面的命令,在除錯時非常有用, 後面會使用到。
實戰2:通過-D設定系統屬性引數
public class TestJVM {
public static void main(String[] args) {
String str = System.getProperty("str");
if (str == null) {
System.out.println("testJVM");
} else {
System.out.println(str);
}
}
}
進行編譯、測試:
#編譯
[[email protected] test]# javac TestJVM.java
#測試
[[email protected] test]# java TestJVM
testJVM
[[email protected] test]# java ‐Dstr=123 TestJVM
123
3.2、-server與-client引數
可以通過-server或-client設定jvm的執行引數。
- 它們的區別是 Server VM的初始堆空間會大一些,預設使用的是並行垃圾回收器,啟動慢執行快。
- Client VM 相對來講會保守一些,初始堆空間會小一些,使用序列的垃圾回收器,它的目標是為了讓JVM的啟動速度更快,但執行速度會比Serverm模式慢些。
- JVM 在啟動的時候會根據硬體和作業系統自動選擇使用Server還是Client型別的JVM。
- 32 位作業系統
- 如果是 Windows系統,不論硬體配置如何,都預設使用Client型別的JVM。
- 如果是其他作業系統上,機器配置有 2GB以上的記憶體同時有2個以上CPU的話預設使用server模式,否則使用client模式。
- 64 位作業系統
- 只有 server型別,不支援client型別。
測試:
[[email protected] test]# java ‐client ‐showversion TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
testJVM
[[email protected] test]# java ‐server ‐showversion TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
itcast
#由於機器是64位系統,所以不支援client模式
4、-X引數
jvm的-X引數是非標準引數,在不同版本的jvm中,引數可能會有所不同,可以通過java -X檢視非標準引數。
[[email protected] test]# java ‐X
‐Xmixed 混合模式執行 (預設)
‐Xint 僅解釋模式執行
‐Xbootclasspath:<用 : 分隔的目錄和 zip/jar 檔案>
設定搜尋路徑以引導類和資源
‐Xbootclasspath/a:<用 : 分隔的目錄和 zip/jar 檔案>
附加在引導類路徑末尾
‐Xbootclasspath/p:<用 : 分隔的目錄和 zip/jar 檔案>
置於引導類路徑之前
‐Xdiag 顯示附加診斷訊息
‐Xnoclassgc 禁用類垃圾收集
‐Xincgc 啟用增量垃圾收集
‐Xloggc:<file> 將 GC 狀態記錄在檔案中 (帶時間戳)
‐Xbatch 禁用後臺編譯
‐Xms<size> 設定初始 Java 堆大小
‐Xmx<size> 設定最大 Java 堆大小
‐Xss<size> 設定 Java 執行緒堆疊大小
‐Xprof 輸出 cpu 配置檔案資料
‐Xfuture 啟用最嚴格的檢查, 預期將來的預設值
‐Xrs 減少 Java/VM 對作業系統訊號的使用 (請參閱文件)
‐Xcheck:jni 對 JNI 函式執行其他檢查
‐Xshare:off 不嘗試使用共享類資料
‐Xshare:auto 在可能的情況下使用共享類資料 (預設)
‐Xshare:on 要求使用共享類資料, 否則將失敗。
‐XshowSettings 顯示所有設定並繼續
‐XshowSettings:all
顯示所有設定並繼續
‐XshowSettings:vm 顯示所有與 vm 相關的設定並繼續
‐XshowSettings:properties
顯示所有屬性設定並繼續
‐XshowSettings:locale
顯示所有與區域設定相關的設定並繼續
‐X 選項是非標準選項, 如有更改, 恕不另行通知。
4.1、-Xint、-Xcomp、-Xmixed
- 在解釋模式 (interpreted mode)下,-Xint標記會強制JVM執行所有的位元組碼,當然這會降低執行速度,通常低10倍或更多。
- -Xcomp 引數與它(-Xint)正好相反,JVM在第一次使用時會把所有的位元組碼編譯成原生代碼,從而帶來最大程度的優化。
然而,很多應用在使用 -Xcomp也會有一些效能損失,當然這比使用-Xint損失的少,原因是-xcomp沒有讓JVM啟用JIT編譯器的全部功能。JIT編譯器可以對是否需要編譯做判斷,如果所有程式碼都進行編譯的話,對於一些只執行一次的程式碼就沒有意義了。
- -Xmixed 是混合模式,將解釋模式與編譯模式進行混合使用,由jvm自己決定,這是jvm預設的模式,也是推薦使用的模式。
示例:強制設定執行模式:
#強制設定為解釋模式
[[email protected] test]# java ‐showversion ‐Xint TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, interpreted mode)
testJVM
#強制設定為編譯模式
[[email protected] test]# java ‐showversion ‐Xcomp TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, compiled mode)
testJVM
#注意:編譯模式下,第一次執行會比解釋模式下執行慢一些,注意觀察。
#預設的混合模式
[[email protected] test]# java ‐showversion TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
testJVM
5、-XX引數
-XX 引數也是非標準引數,主要用於jvm的調優和debug操作。
-XX引數的使用有2種方式,一種是boolean型別,一種是非boolean型別:
boolean 型別:
- 格式: -XX:[+-]
- 如: -XX:+DisableExplicitGC 表示禁用手動呼叫gc操作,也就是說呼叫System.gc()無效
非 boolean型別:
- 格式: -XX:
- 如: -XX:NewRatio=1 表示新生代和老年代的比值
- 用法:
[[email protected] test]# java ‐showversion ‐XX:+DisableExplicitGC TestJVM
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
testJVM
6、-Xms與-Xmx引數
-Xms與-Xmx分別是設定jvm的堆記憶體的初始大小和最大大小。
- -Xmx2048m:等價於-XX:MaxHeapSize,設定JVM最大堆記憶體為2048M。
- -Xms512m:等價於-XX:InitialHeapSize,設定JVM初始堆記憶體為512M。
適當的調整jvm的記憶體大小,可以充分利用伺服器資源,讓程式跑的更快。
示例:
[[email protected] test]# java ‐Xms512m ‐Xmx2048m TestJVM
testJVM
7、檢視jvm的執行引數
有些時候我們需要檢視jvm的執行引數,這個需求可能會存在2種情況:
- 執行 java命令時打印出執行引數;
- 檢視正在執行的java程序的引數;
7.1、執行java命令時列印引數
執行java命令時列印引數,需要新增-XX:+PrintFlagsFinal引數即可。
[[email protected] test]# java ‐XX:+PrintFlagsFinal ‐version
[Global flags]
uintx AdaptiveSizeDecrementScaleFactor = 4
{product}
uintx AdaptiveSizeMajorGCDecayTimeScale = 10
{product}
uintx AdaptiveSizePausePolicy = 0
{product}
uintx AdaptiveSizePolicyCollectionCostMargin = 50
{product}
uintx AdaptiveSizePolicyInitializingSteps = 20
{product}
uintx AdaptiveSizePolicyOutputInterval = 0
{product}
uintx AdaptiveSizePolicyWeight = 10
{product}
uintx AdaptiveSizeThroughPutPolicy = 0
{product}
uintx AdaptiveTimeWeight = 25
{product}
bool AdjustConcurrency = false
{product}
bool AggressiveOpts = false
{product}
intx AliasLevel = 3
{C2 product}
bool AlignVector = true
{C2 product}
intx AllocateInstancePrefetchLines = 1
{product}
intx AllocatePrefetchDistance = 256
{product}
intx AllocatePrefetchInstr = 0
{product}
…………………………略…………………………………………
bool UseXmmI2D = false
{ARCH product}
bool UseXmmI2F = false
{ARCH product}
bool UseXmmLoadAndClearUpper = true
{ARCH product}
bool UseXmmRegToRegMoveAll = true
{ARCH product}
bool VMThreadHintNoPreempt = false
{product}
intx VMThreadPriority = ‐1
{product}
intx VMThreadStackSize = 1024
{pd product}
intx ValueMapInitialSize = 11
{C1 product}
intx ValueMapMaxLoopSize = 8
{C1 product}
intx ValueSearchLimit = 1000
{C2 product}
bool VerifyMergedCPBytecodes = true
{product}
bool VerifySharedSpaces = false
{product}
intx WorkAroundNPTLTimedWaitHang = 1
{product}
uintx YoungGenerationSizeIncrement = 20
{product}
uintx YoungGenerationSizeSupplement = 80
{product}
uintx YoungGenerationSizeSupplementDecay = 8
{product}
uintx YoungPLABSize = 4096
{product}
bool ZeroTLAB = false
{product}
intx hashCode = 5
{product}
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
由上述的資訊可以看出,引數有 boolean型別和數字型別,值的操作符是=或:=,分別代表預設值和被修改的值。
示例:
java ‐XX:+PrintFlagsFinal ‐XX:+VerifySharedSpaces ‐version
intx ValueMapInitialSize = 11
{C1 product}
intx ValueMapMaxLoopSize = 8
{C1 product}
intx ValueSearchLimit = 1000
{C2 product}
bool VerifyMergedCPBytecodes = true
{product}
bool VerifySharedSpaces := true
{product}
intx WorkAroundNPTLTimedWaitHang = 1
{product}
uintx YoungGenerationSizeIncrement = 20
{product}
uintx YoungGenerationSizeSupplement = 80
{product}
uintx YoungGenerationSizeSupplementDecay = 8
{product}
uintx YoungPLABSize = 4096
{product}
bool ZeroTLAB = false
{product}
intx hashCode = 5
{product}
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141‐b15)
Java HotSpot(TM) 64‐Bit Server VM (build 25.141‐b15, mixed mode)
#可以看到VerifySharedSpaces這個引數已經被修改了。
7.2、檢視正在執行的jvm引數
如果想要檢視正在執行的jvm就需要藉助於jinfo命令檢視。
首先,啟動一個 tomcat用於測試,來觀察下執行的jvm引數。
cd /tmp/
rz 上傳
tar ‐xvf apache‐tomcat‐7.0.57.tar.gz
cd apache‐tomcat‐7.0.57
cd bin/
./startup.sh
#http://192.168.40.133:8080/ 進行訪問
#檢視所有的引數,用法:jinfo ‐flags <程序id>
#通過jps 或者 jps ‐l 檢視java程序
[[email protected] bin]# jps
6346 Jps
6219 Bootstrap
[[email protected] bin]# jps ‐l
6358 sun.tools.jps.Jps
6219 org.apache.catalina.startup.Bootstrap
[[email protected] bin]#
[[email protected] bin]# jinfo ‐flags 6219
Attaching to process ID 6219, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.141‐b15
Non‐default VM flags: ‐XX:CICompilerCount=2 ‐XX:InitialHeapSize=31457280
‐XX:MaxHeapSize=488636416 ‐XX:MaxNewSize=162529280 ‐
XX:MinHeapDeltaBytes=524288 ‐XX:NewSize=10485760 ‐XX:OldSize=20971520 ‐
XX:+UseCompressedClassPointers ‐XX:+UseCompressedOops ‐
XX:+UseFastUnorderedTimeStamps ‐XX:+UseParallelGC
Command line: ‐Djava.util.logging.config.file=/tmp/apache‐tomcat‐
7.0.57/conf/logging.properties ‐
Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager ‐
Djava.endorsed.dirs=/tmp/apache‐tomcat‐7.0.57/endorsed ‐
Dcatalina.base=/tmp/apache‐tomcat‐7.0.57 ‐Dcatalina.home=/tmp/apache‐
tomcat‐7.0.57 ‐Djava.io.tmpdir=/tmp/apache‐tomcat‐7.0.57/temp
#檢視某一引數的值,用法:jinfo ‐flag <引數名> <程序id>
[[email protected] bin]# jinfo ‐flag MaxHeapSize 6219
‐XX:MaxHeapSize=488636416