博客 / 詳情

返回

JVM 11 調優指南:如何進行JVM調優,JVM調優參數

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,有大廠完整面經,工作技術,架構師成長之路,等經驗分享

user avatar markerhub 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.