公司項目 jdk 版本為 1.8, JVM 參數是自定義設置的,gradle 中 JVM 配置如下(默認內存為 8 G):
applicationDefaultJvmArgs = ["-Xms1G", "-Xmx2G", "-Xss256k", "-Djava.awt.headless=true", "-Dfile.encoding=UTF-8",
"-XX:MetaspaceSize=256M", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=200", "-XX:G1HeapRegionSize=2M",
"-XX:+UseStringDeduplication", "-XX:+PrintStringDeduplicationStatistics",
"-XX:ParallelGCThreads=4", "-XX:ConcGCThreads=2", "-XX:MaxDirectMemorySize=1024M",
"-XX:+PrintGCDetails", "-XX:+PrintGCDateStamps", "-Xloggc:/tmp/gc.log", "-XX:+PrintTenuringDistribution",
"-XX:+DoEscapeAnalysis", "-XX:+EliminateAllocations", "-Dlogging.config=File:/config/logback.xml"]
各個參數的含義:
- -Xms1G:堆的初始內存容量為 1G
- -Xmx2G:堆的最大內存容量為 2G
- -Xss256k:Java 棧的容量為 256K(不區分虛擬機棧和本地方法棧),經測試,此時棧的高度可以達到 1500+
- -Djava.awt.headless=true:java.awt 下的類使用無頭模式,跟 GUI 相關
- -Dfile.encoding=UTF-8:文件編碼為 UTF-8,不指定時默認使用系統的文件編碼
- MetaspaceSize=256M:元數據區容量為 256M,默認是-1,即不限制,或者說只受限於本地內存大小
- -XX:+UseG1GC:堆回收使用 G1 垃圾收集器
- -XX:MaxGCPauseMillis=200:G1 參數,GC 發生之前最大停頓時間為 200 ms,這是一個軟目標,JVM 將盡最大努力實現
- -XX:+UseStringDeduplication:消除具有相同字符的重復 String 對象
- -XX:+PrintStringDeduplicationStatistics:String 重復數據刪除統計分析,相關統計分析將輸出到錯誤控制台
- -XX:ParallelGCThreads=4:G1 參數,垃圾收集器並行階段使用線程為 4 個,默認值根據 JVM 運行的平台而定
- -XX:ConcGCThreads=2:G1 參數,並發垃圾收集器將使用的線程數為 2 個,默認值根據 JVM 運行的平台而定
- -XX:MaxDirectMemorySize=1024M:最大直接內存為 1024M,默認與 Java 堆最大值(由-Xmx 指定)一致
- -XX:+PrintGCDetails:每次垃圾回收完成后,打印一條帶有更多詳細信息的長消息
- -XX:+PrintGCDateStamps:發生垃圾回收時,打印相對於 JVM 啟動時間的時間戳,默認關閉
- -Xloggc:/tmp/gc.log:將 GC 詳細輸出記錄到指定文件 /tmp/gc.log,
- -XX:+PrintTenuringDistribution:開啟可打印任職(存活)年齡信息,默認關閉
- -XX:+DoEscapeAnalysis:關閉轉義分析的使用,默認開啟
- -XX:+EliminateAllocations:關閉變量替換優化,默認開啟
- -Dlogging.config=File:/config/logback.xml:log 日志使用 config 下的 logback.xml 配置文件
參數含義來源:
查看 -X
開頭參數:
$ java -X
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
查看所有 -XX:
開頭參數的配置:
$ java -XX:+PrintFlagsFinal -version
垃圾收集器
64 位的虛擬機默認使用的就是服務端模式
,通過 java -version
可以看出(Server):
$ java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
JDK 1.8 默認 JVM 參數:初始容量 Xms 128M,最大容量 Xmx 2G,使用 -XX:+UseParallelGC
。
$ java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
根據 RednaxelaFX 的回答,雖然 jconsole 顯示使用 -XX:+UseParallelGC
時,但 jdk 1.8 默認會開啟 XX:+UseParallelOldGC
。 此時收集器使用 Parallel Scavenge + Parallel Old
組合。
此種組合適用於注重吞吐量或者處理器資源較為稀缺的場合。
jdk1.8 可以使用更為先進的收集器 G1(Garbage First),它是 JDK 9 服務端模式默認的垃圾收集器。G1 也是遵循分代收集理論設計,它將內存分為大小相等的獨立區域(Region),每個 Region 都可以根據需要,扮演新生代的 Eden 空間、Survivor 空間,或者老年代空間。回收時,不像其他收集器,只針對某個區域,Major GC(新生代)或 Full GC(老年代)或 Full GC(整個堆),而是將多個 Region 組成回收集(Collection Set)進行回收(MixedGC)。
G1 收集器跟蹤每個 Region 里面的垃圾堆積的「價值」大小,價值即回收所獲得的空間大小以及回收所需時間的經驗值,然后在后台維護一個優先列表,再根據用戶設定允許的收集停頓時間(MaxGCPauseMillis),優先處理回收價值收益最大的那些 Region,這也就是 「Garbage First」名字的由來。回收時,不追求一次把 Java 堆全部清理干凈,而是追求能夠應付應用的內存分配速率(Allocation Rate),只要收集的速度能跟得上對象分配的速度就行。
G1 相比 Parallel Scavenge + Parallel Old
組合的最大優點:可以指定最大收集停頓時間來調節。
Maven 項目如何使用這些參數
利用 Maven Wrapper,在 .mvn/jvm.config
中配置:
-Xms1G -Xmx2G -Xss256k -Djava.awt.headless=true -Dfile.encoding=UTF-8 -XX:MetaspaceSize=256M -XX:+UseG1GC -XX:MaxGCPauseMillis=200 ...
打包時使用 mvnw
命令,如:mvnw clean package