JVM 11的優化指南:如何進行JVM調優,以及JVM調優參數有哪些”這篇文章將包含JVM 11調優的核心概念、重要性、調優參數,並提供12個實用的代碼示例,每個示例都會結合JVM調優參數和Java代碼
本文已收錄於,我的技術網站 ddkk.com,有大廠完整面經,工作技術,架構師成長之路,等經驗分享
JVM 11的優化指南
JVM調優簡介
JVM調優是通過調整Java虛擬機的配置參數來提升應用程序的性能和資源利用效率的過程。這包括調整堆內存大小、選擇合適的垃圾收集器,以及調整其他性能相關的參數。
JVM調優的重要性
- 提高性能:通過調優,可以提升應用程序的響應速度和處理能力。
- 資源優化:合理的配置可以使應用更高效地利用系統資源。
- 穩定性增強:避免過度的資源消耗和頻繁的垃圾回收,從而提高應用的穩定性。
JVM 11調優參數
- 堆內存設置:-Xms 和 -Xmx 設置堆的起始大小和最大大小。
- 垃圾收集器選擇:-XX:+UseG1GC 使用G1垃圾收集器,適用於大堆和多核處理器。
- 性能監控:-XX:+PrintGCDetails 和 -XX:+PrintGCDateStamps 打印垃圾收集細節。
企業級 JVM 11 的調優參數,機器配置是8核32G
為配置有8核和32GB內存的機器推薦JVM 11調優參數時,需考慮應用的類型、負載特性等。以下是一套企業級的JVM調優參數推薦,適用於大多數中大型Java應用:
1、堆內存設置
- -Xms16g:設置初始堆內存為16GB。這個設置使得JVM在啓動時即分配較大內存,減少運行時動態擴展帶來的性能損耗。
- -Xmx16g:設置最大堆內存為16GB。這樣做可以防止頻繁的垃圾回收,並保證應用程序有足夠的內存。
2、垃圾收集器選擇
- -XX:+UseG1GC:使用G1垃圾收集器,適用於需要快速響應和大內存管理的應用。
3、G1垃圾收集器的進一步優化
- -XX:MaxGCPauseMillis=200:儘可能將GC暫停時間控制在200毫秒以內,以減少應用停頓。
- -XX:ParallelGCThreads=8:設置並行GC線程數,通常設置為CPU核心數。
- -XX:ConcGCThreads=4:設置G1垃圾回收器的併發線程數,通常為ParallelGCThreads的一半。
4、元空間設置
- -XX:MetaspaceSize=256m:設置初始元空間大小為256MB。
- -XX:MaxMetaspaceSize=512m:設置最大元空間大小為512MB,以防止元空間過度使用內存。
5、GC日誌記錄
- -Xlog:gc*:file=gc.log:time,level:filecount=5,filesize=20M:配置GC日誌輸出,包括日誌文件的位置、大小和輪轉。
6、性能調優
- -XX:+UseStringDeduplication:開啓字符串去重功能,減少堆內存的佔用。
- -XX:+DisableExplicitGC:禁用顯式GC調用(如System.gc() ),避免不必要的GC操作。
7、高級調優選項
- -XX:+UnlockExperimentalVMOptions:解鎖實驗性VM選項,用於開啓一些最新的優化功能。
- -XX:+UseLargePages:啓用大頁面支持,有助於提高大內存機器的性能。
注意事項
- 根據應用的實際性能和資源使用情況調整這些參數。
- 應用性能監控工具可以幫助您更好地理解應用運行情況。
- 在生產環境中逐漸調整參數,並密切關注每次調整後的影響。
合理的JVM調優可以顯著提升應用的性能和穩定性。不過,請記得調優是一個持續的過程,需要根據應用的具體表現來不斷調整和優化。
實用代碼示例
示例1:設置和監控堆內存大小
JVM啓動參數:
java -Xms512m -Xmx1g -jar YourApp.jar
- -Xms512m:設置初始堆內存為512MB。
- -Xmx1g:設置最大堆內存為1GB。
Java代碼:
public class HeapSizeMonitoring {
public static void main(String[] args) {
// 獲取運行時環境
Runtime runtime = Runtime.getRuntime();
// 打印JVM的初始內存和最大內存配置
System.out.println("JVM初始內存大小:" + runtime.totalMemory() / (1024 * 1024) + " MB");
System.out.println("JVM最大內存大小:" + runtime.maxMemory() / (1024 * 1024) + " MB");
}
}
此代碼示例演示瞭如何在Java應用程序中監控當前JVM的堆內存使用情況。
示例2:使用G1垃圾收集器並監控GC
JVM啓動參數:
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
- -XX:+UseG1GC:使用G1垃圾收集器。
- -XX:MaxGCPauseMillis=200:設置期望的最大GC暫停時間為200毫秒。
- -XX:+PrintGCDetails 和 -XX:+PrintGCDateStamps:打印GC的詳細信息和時間戳。
Java代碼:
import java.util.ArrayList;
import java.util.List;
public class G1GCExample {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1024 * 1024]); // 每次分配1MB的空間
if (list.size() > 100) {
list.clear(); // 清空列表以釋放內存
}
}
}
}
此代碼示例展示了在使用G1垃圾收集器時的內存分配和清理過程。
示例3:線程堆棧大小的設置與監控
JVM啓動參數:
java -Xss256k -jar YourApp.jar
- -Xss256k:設置每個線程的堆棧大小為256KB。
Java代碼:
javaCopy code
public class ThreadStackSizeExample {
public static void main(String[] args) {
// 創建並啓動一個新線程
Thread thread = new Thread(() -> {
try {
Thread.sleep(10000); // 讓線程休眠一段時間
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
System.out.println("線程堆棧大小設置為256KB...");
}
}
這段代碼展示瞭如何設置線程的堆棧大小,並創建一個簡單的線程來展示這一設置的實際應用。
示例4:使用G1垃圾收集器並調優
JVM啓動參數:
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
- -XX:+UseG1GC:使用G1垃圾收集器。
- -XX:MaxGCPauseMillis=200:嘗試將GC的最大暫停時間控制在200毫秒以內。
- -XX:InitiatingHeapOccupancyPercent=45:當堆佔用率達到45%時開始GC。
- -XX:+PrintGCDetails 和 -XX:+PrintGCDateStamps:打印詳細的GC信息和時間戳。
Java代碼:
import java.util.ArrayList;
import java.util.List;
public class G1GCExample {
public static void main(String[] args) {
System.out.println("G1垃圾收集器已啓用,GC的詳細信息和時間戳將被打印...");
// 創建一個列表,用於存儲分配的內存塊
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
// 每次循環分配1MB的內存塊
list.add(new byte[1024 * 1024]);
// 每當列表中有100個內存塊時,清空列表,釋放內存
if (list.size() >= 100) {
list.clear();
// 建議執行一次垃圾收集
System.gc();
}
}
}
}
此代碼示例展示瞭如何在使用G1垃圾收集器的情況下進行內存分配和清理。
示例5:監控垃圾收集信息
JVM啓動參數:
java -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
- -XX:+PrintGC:打印基本的GC信息。
- -XX:+PrintGCDetails:打印GC的詳細信息。
- -XX:+PrintGCDateStamps:在GC日誌中加入時間戳。
Java代碼:
import java.util.concurrent.TimeUnit;
public class GCMonitoringExample {
public static void main(String[] args) throws InterruptedException {
System.out.println("垃圾收集信息監控已啓用,GC的基本信息、詳細信息和時間戳將被打印...");
// 分配內存並稍作等待,以便觀察GC的行為
byte[] allocation1 = new byte[512 * 1024 * 1024]; // 分配約512MB的空間
TimeUnit.SECONDS.sleep(10); // 睡眠10秒
byte[] allocation2 = new byte[512 * 1024 * 1024]; // 再分配約512MB的空間
TimeUnit.SECONDS.sleep(10); // 睡眠10秒
// 提示垃圾收集
System.gc();
}
}
此代碼示例演示瞭如何通過分配大量內存並加入等待時間來觀察GC的行為,同時啓用了詳細的GC信息打印。
示例6:設置線程堆棧大小
JVM啓動參數:
java -Xss1024k -jar YourApp.jar
- -Xss1024k:設置每個線程的堆棧大小為1024KB。
Java代碼:
public class ThreadStackSizeExample {
public static void main(String[] args) {
System.out.println("線程堆棧大小已設置為1024KB...");
// 創建並啓動一個新線程,展示設置的堆棧大小
Thread thread = new Thread(() -> {
recursiveMethod(0);
});
thread.start();
}
// 一個簡單的遞歸方法,用於演示堆棧的深度
private static void recursiveMethod(int depth) {
if (depth < 1000) {
recursiveMethod(depth + 1);
} else {
System.out.println("達到遞歸深度:" + depth);
}
}
}
這段代碼設置了線程的堆棧大小,並通過遞歸調用來測試堆棧深度的限制。
示例7:監控類的加載和卸載
JVM啓動參數:
java -XX:+TraceClassLoading -XX:+TraceClassUnloading -jar YourApp.jar
- -XX:+TraceClassLoading:啓用類加載跟蹤。
- -XX:+TraceClassUnloading:啓用類卸載跟蹤。
Java代碼:
public class ClassLoadingMonitoring {
public static void main(String[] args) {
System.out.println("類加載和卸載監控已啓動,相關信息將打印到控制枱...");
// 這裏不需要特定的Java代碼來觸發類的加載或卸載
// 類加載和卸載的信息將通過JVM參數直接打印到控制枱
// 可以考慮加載一些額外的類或使用ClassLoader來觀察輸出
}
}
此代碼示例用於展示如何開啓和查看JVM的類加載和卸載信息,對於理解類的生命週期非常有用。
示例8:監控垃圾回收行為
JVM啓動參數:
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -jar YourApp.jar
- -XX:+PrintGCDetails:打印垃圾回收的詳細信息。
- -XX:+PrintGCDateStamps:在垃圾回收日誌中加入時間戳。
- -Xloggc:gc.log:將垃圾回收日誌記錄到指定文件。
Java代碼:
import java.util.ArrayList;
import java.util.List;
public class GCMonitoringExample {
public static void main(String[] args) {
System.out.println("垃圾回收監控已啓用,詳細信息將記錄到日誌文件...");
// 創建一個列表,用於模擬內存佔用
List<Object> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(new Object());
// 每1000個對象後進行一次清理,模擬內存釋放
if (i % 1000 == 0) {
list.clear();
System.gc(); // 手動請求垃圾回收
}
}
}
}
此代碼示例展示瞭如何通過創建對象並在特定時刻清理,以觸發和監控垃圾回收過程。
示例9:配置和使用字符串去重功能
JVM啓動參數:
java -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -jar YourApp.jar
- -XX:+UseStringDeduplication:開啓JVM的字符串去重功能。
- -XX:+PrintStringDeduplicationStatistics:打印字符串去重的統計信息。
Java代碼:
public class StringDeduplicationExample {
public static void main(String[] args) {
System.out.println("字符串去重功能已啓用,相關統計信息將打印...");
// 創建一個字符串列表
List<String> stringList = new ArrayList<>();
// 添加大量重複字符串,觸發字符串去重
for (int i = 0; i < 100000; i++) {
stringList.add("Hello, JVM!"); // 添加重複的字符串
}
// 觸發垃圾回收,以便觀察字符串去重效果
System.gc();
}
}
此代碼示例通過創建大量重複的字符串,並觸發垃圾回收,來展示字符串去重功能的效果。
示例10:使用並行垃圾收集器
JVM啓動參數:
java -XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:+PrintGCDetails -jar YourApp.jar
- -XX:+UseParallelGC:使用並行垃圾收集器。
- -XX:GCTimeRatio=4:設置吞吐量目標,表示99%的時間用於應用程序,1%的時間用於垃圾收集。
- -XX:+PrintGCDetails:打印垃圾收集的詳細信息。
Java代碼:
public class ParallelGCMonitoring {
public static void main(String[] args) {
System.out.println("並行垃圾收集器已啓用,GC詳細信息正在打印...");
// 這裏模擬一些內存分配以觸發GC
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(new byte[1024 * 1024]); // 每次分配1MB的空間
}
// 清理引用,觸發GC
list.clear();
System.gc(); // 建議執行垃圾收集
}
}
這段代碼用於演示並行垃圾收集器的使用,通過分配內存並清理來觸發垃圾收集。
示例11:配置和使用String去重功能
JVM啓動參數:
java -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -jar YourApp.jar
- -XX:+UseStringDeduplication:開啓JVM的字符串去重功能。
- -XX:+PrintStringDeduplicationStatistics:打印字符串去重的統計信息。
Java代碼:
public class StringDeduplicationExample {
public static void main(String[] args) {
System.out.println("字符串去重功能已啓用,統計信息正在打印...");
// 創建重複的字符串
String repeatedString = "Hello, World!";
List<String> stringList = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
stringList.add(new String(repeatedString)); // 通過new創建新的字符串實例
}
// 建議執行垃圾收集來觸發字符串去重
System.gc();
}
}
這段代碼通過創建大量重複的字符串實例,演示了字符串去重功能的效果。
示例12:設置和監控ZGC垃圾收集器
JVM啓動參數:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc -jar YourApp.jar
- -XX:+UnlockExperimentalVMOptions:解鎖實驗性VM選項。
- -XX:+UseZGC:使用ZGC垃圾收集器。
- -Xlog:gc:開啓GC日誌。
Java代碼:
import java.util.concurrent.TimeUnit;
public class ZGCMonitoring {
public static void main(String[] args) throws InterruptedException {
System.out.println("ZGC垃圾收集器已啓用,GC日誌正在輸出...");
// 創建對象並模擬短暫的暫停,觸發GC
for (int i = 0; i < 100; i++) {
byte[] allocation = new byte[10 * 1024 * 1024]; // 分配約10MB的空間
TimeUnit.MILLISECONDS.sleep(100); // 暫停100毫秒
}
}
}
此代碼示例演示瞭如何使用ZGC垃圾收集器,並通過分配內存和短暫暫停來觸發垃圾收集。
結語
合理的JVM調優可以顯著提升應用的性能和穩定性。不過,請記得調優是一個持續的過程,需要根據應用的具體表現來不斷調整和優化。
本文已收錄於,我的技術網站 ddkk.com,有大廠完整面經,工作技術,架構師成長之路,等經驗分享