11-Java语言核心-JVM原理-JVM调优详解

JVM调优详解

一、知识概述

JVM调优是Java应用性能优化的重要环节。通过合理配置JVM参数、分析GC行为、优化内存使用,可以显著提升应用性能。理解JVM调优需要在掌握JVM原理的基础上,结合实际应用场景进行实践。

调优目标

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                       JVM调优目标                                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. 性能目标                                                        │
│     ┌───────────────┐   ┌───────────────┐   ┌───────────────┐      │
│     │   低延迟      │   │   高吞吐量    │   │   小内存占用  │      │
│     │  响应时间快   │   │  批处理效率高 │   │  资源利用率高 │      │
│     └───────────────┘   └───────────────┘   └───────────────┘      │
│                                                                     │
│  2. 稳定性目标                                                      │
│     ┌───────────────┐   ┌───────────────┐   ┌───────────────┐      │
│     │  无OOM异常    │   │  GC停顿可控  │   │  内存无泄漏   │      │
│     └───────────────┘   └───────────────┘   └───────────────┘      │
│                                                                     │
│  3. 可预测性目标                                                    │
│     ┌───────────────┐   ┌───────────────┐                         │
│     │  性能可预测   │   │  资源可控    │                          │
│     └───────────────┘   └───────────────┘                         │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

调优公式:
  吞吐量 = 运行用户代码时间 / (运行用户代码时间 + GC时间)
  停顿时间 = STW(Stop-The-World)时间总和
  内存占用 = 堆内存 + 非堆内存

调优原则

  1. 不要过早优化 - 先保证正确性,再优化性能
  2. 基于数据调优 - 使用监控工具收集数据
  3. 逐步调优 - 每次只调整一个参数
  4. 对比验证 - 调优前后对比测试

二、知识点详细讲解

2.1 常用JVM参数

2.1.1 内存参数
java 复制代码
/**
 * JVM内存参数详解
 */
public class MemoryParametersDemo {
    
    public static void main(String[] args) {
        System.out.println("=== JVM内存参数 ===\n");
        
        printHeapParameters();
        printMetaspaceParameters();
        printThreadParameters();
        printDirectMemoryParameters();
    }
    
    private static void printHeapParameters() {
        System.out.println("【堆内存参数】\n");
        
        /*
        ┌─────────────────────────────────────────────────────────────┐
        │                     堆内存配置示例                           │
        ├─────────────────────────────────────────────────────────────┤
        │                                                             │
        │  -Xms4g        初始堆大小 4GB                               │
        │  -Xmx4g        最大堆大小 4GB                               │
        │  -Xmn2g        新生代大小 2GB                               │
        │                                                             │
        │  ┌─────────────────────────────────────────────────────┐   │
        │  │                    Java Heap (4GB)                   │   │
        │  ├─────────────────────────────────────────────────────┤   │
        │  │  ┌───────────────────┐  ┌───────────────────┐      │   │
        │  │  │   新生代 (2GB)    │  │   老年代 (2GB)    │      │   │
        │  │  │  Eden | S0 | S1  │  │                  │      │   │
        │  │  └───────────────────┘  └───────────────────┘      │   │
        │  └─────────────────────────────────────────────────────┘   │
        │                                                             │
        └─────────────────────────────────────────────────────────────┘
        */
        
        System.out.println("基本参数:");
        System.out.println("  -Xms<size>       初始堆大小");
        System.out.println("  -Xmx<size>       最大堆大小");
        System.out.println("  -Xmn<size>       新生代大小");
        System.out.println();
        
        System.out.println("比例参数:");
        System.out.println("  -XX:NewRatio=2           新生代:老年代 = 1:2");
        System.out.println("  -XX:SurvivorRatio=8      Eden:Survivor = 8:1:1");
        System.out.println("  -XX:MaxTenuringThreshold=15  晋升年龄阈值");
        System.out.println("  -XX:PretenureSizeThreshold  大对象阈值");
        System.out.println();
        
        System.out.println("推荐配置:");
        System.out.println("  -Xms和-Xmx设为相同值(避免动态扩容)");
        System.out.println("  堆大小建议为物理内存的50%-80%");
        System.out.println("  根据对象存活率调整新生代比例");
        System.out.println();
        
        System.out.println("示例配置:");
        System.out.println("  java -Xms4g -Xmx4g -Xmn2g -XX:SurvivorRatio=8 -jar app.jar");
        System.out.println();
    }
    
    private static void printMetaspaceParameters() {
        System.out.println("【元空间参数】\n");
        
        /*
        JDK 8+: 元空间使用本地内存
        JDK 7及之前: 永久代使用JVM堆内存
        */
        
        System.out.println("元空间参数:");
        System.out.println("  -XX:MetaspaceSize=256m        初始元空间大小");
        System.out.println("  -XX:MaxMetaspaceSize=512m     最大元空间大小");
        System.out.println("  -XX:MinMetaspaceFreeRatio=40  最小空闲比例");
        System.out.println("  -XX:MaxMetaspaceFreeRatio=70  最大空闲比例");
        System.out.println();
        
        System.out.println("永久代参数(JDK 7):");
        System.out.println("  -XX:PermSize=256m             初始永久代大小");
        System.out.println("  -XX:MaxPermSize=512m          最大永久代大小");
        System.out.println();
        
        System.out.println("调优建议:");
        System.out.println("  - 类加载多的应用需要增大元空间");
        System.out.println("  - 动态代理、CGLib生成类多的应用");
        System.out.println("  - 设置合理的MaxMetaspaceSize避免无限制增长");
        System.out.println();
    }
    
    private static void printThreadParameters() {
        System.out.println("【线程参数】\n");
        
        System.out.println("线程栈参数:");
        System.out.println("  -Xss512k         线程栈大小");
        System.out.println();
        
        System.out.println("调优说明:");
        System.out.println("  - 默认: Linux 1MB, Windows 320KB");
        System.out.println("  - 递归深的程序可增大(如-Xss2m)");
        System.out.println("  - 线程多的程序可减小(如-Xss256k)");
        System.out.println("  - 总栈内存 = 线程数 × 栈大小");
        System.out.println();
    }
    
    private static void printDirectMemoryParameters() {
        System.out.println("【直接内存参数】\n");
        
        System.out.println("直接内存参数:");
        System.out.println("  -XX:MaxDirectMemorySize=1g    最大直接内存");
        System.out.println();
        
        System.out.println("适用场景:");
        System.out.println("  - NIO应用(Netty、Kafka等)");
        System.out.println("  - 大文件IO");
        System.out.println("  - 零拷贝场景");
        System.out.println();
        
        System.out.println("说明:");
        System.out.println("  - 默认等于最大堆大小");
        System.out.println("  - 超出限制抛出OutOfMemoryError: Direct buffer memory");
        System.out.println();
    }
}
2.1.2 GC参数
java 复制代码
/**
 * GC参数详解
 */
public class GCParametersDemo {
    
    public static void main(String[] args) {
        System.out.println("=== GC参数 ===\n");
        
        printGCSelector();
        printGCConfiguration();
        printGCTuning();
    }
    
    private static void printGCSelector() {
        System.out.println("【GC选择参数】\n");
        
        System.out.println("JDK 8:");
        System.out.println("  -XX:+UseSerialGC              Serial GC");
        System.out.println("  -XX:+UseParallelGC            Parallel GC (默认)");
        System.out.println("  -XX:+UseParallelOldGC         Parallel Old GC");
        System.out.println("  -XX:+UseConcMarkSweepGC       CMS GC");
        System.out.println("  -XX:+UseG1GC                  G1 GC");
        System.out.println();
        
        System.out.println("JDK 11+:");
        System.out.println("  -XX:+UseG1GC                  G1 GC (默认)");
        System.out.println("  -XX:+UseZGC                   ZGC");
        System.out.println("  -XX:+UseShenandoahGC          Shenandoah GC");
        System.out.println();
        
        System.out.println("JDK 21+:");
        System.out.println("  -XX:+UseZGC -XX:+ZGenerational  分代ZGC");
        System.out.println();
        
        System.out.println("选择建议:");
        System.out.println("┌─────────────────┬────────────────────┐");
        System.out.println("│ 场景            │ 推荐GC             │");
        System.out.println("├─────────────────┼────────────────────┤");
        System.out.println("│ 单核/小内存     │ Serial GC          │");
        System.out.println("│ 多核/吞吐优先   │ Parallel GC        │");
        System.out.println("│ 多核/延迟优先   │ G1 GC              │");
        System.out.println("│ 大堆/低延迟     │ ZGC                │");
        System.out.println("└─────────────────┴────────────────────┘");
        System.out.println();
    }
    
    private static void printGCConfiguration() {
        System.out.println("【GC配置参数】\n");
        
        System.out.println("Parallel GC:");
        System.out.println("  -XX:MaxGCPauseMillis=200      最大停顿时间目标");
        System.out.println("  -XX:GCTimeRatio=99            吞吐量目标");
        System.out.println("  -XX:ParallelGCThreads=8       GC线程数");
        System.out.println();
        
        System.out.println("CMS GC (JDK 8):");
        System.out.println("  -XX:CMSInitiatingOccupancyFraction=75  老年代占用阈值");
        System.out.println("  -XX:+UseCMSCompactAtFullCollection     Full GC时压缩");
        System.out.println("  -XX:CMSFullGCsBeforeCompaction=0       压缩间隔");
        System.out.println("  -XX:+CMSParallelRemarkEnabled          并行重新标记");
        System.out.println();
        
        System.out.println("G1 GC:");
        System.out.println("  -XX:MaxGCPauseMillis=200      最大停顿时间");
        System.out.println("  -XX:G1HeapRegionSize=4m       Region大小");
        System.out.println("  -XX:InitiatingHeapOccupancyPercent=45  堆占用阈值");
        System.out.println("  -XX:G1ReservePercent=15       预留空间");
        System.out.println("  -XX:G1HeapWastePercent=5      浪费空间阈值");
        System.out.println();
        
        System.out.println("ZGC:");
        System.out.println("  -XX:ZCollectionInterval=5     GC触发间隔(ms)");
        System.out.println("  -XX:ZAllocationSpikeTolerance=2  分配峰值容忍度");
        System.out.println("  -XX:ConcGCThreads=2           并发GC线程数");
        System.out.println();
    }
    
    private static void printGCTuning() {
        System.out.println("【GC调优参数】\n");
        
        System.out.println("对象晋升:");
        System.out.println("  -XX:MaxTenuringThreshold=15   晋升年龄阈值");
        System.out.println("  -XX:TargetSurvivorRatio=50    Survivor目标使用率");
        System.out.println();
        
        System.out.println("大对象处理:");
        System.out.println("  -XX:PretenureSizeThreshold=1m  大对象阈值(字节)");
        System.out.println("  -XX:+UseTLAB                  使用TLAB(默认开启)");
        System.out.println("  -XX:TLABSize=256k             TLAB大小");
        System.out.println();
        
        System.out.println("GC日志(JDK 8):");
        System.out.println("  -XX:+PrintGCDetails           详细GC信息");
        System.out.println("  -XX:+PrintGCDateStamps        日期时间戳");
        System.out.println("  -XX:+PrintGCTimeStamps        相对时间戳");
        System.out.println("  -XX:+PrintGCApplicationStoppedTime  停顿时间");
        System.out.println("  -Xloggc:gc.log                日志文件");
        System.out.println("  -XX:+UseGCLogFileRotation     日志轮转");
        System.out.println("  -XX:NumberOfGCLogFiles=10     日志文件数");
        System.out.println("  -XX:GCLogFileSize=10m         单文件大小");
        System.out.println();
        
        System.out.println("GC日志(JDK 11+):");
        System.out.println("  -Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=10,filesize=10m");
        System.out.println();
    }
}

2.2 监控工具

2.2.1 命令行工具
java 复制代码
/**
 * JVM监控命令行工具
 */
public class CommandLineToolsDemo {
    
    public static void main(String[] args) {
        System.out.println("=== JVM监控命令行工具 ===\n");
        
        jpsDemo();
        jstatDemo();
        jmapDemo();
        jstackDemo();
        jinfoDemo();
    }
    
    private static void jpsDemo() {
        System.out.println("【jps - Java进程状态工具】\n");
        
        /*
        jps [options] [hostid]
        
        作用: 列出正在运行的Java进程
        */
        
        System.out.println("常用命令:");
        System.out.println("  jps                列出Java进程");
        System.out.println("  jps -l             显示主类全名");
        System.out.println("  jps -m             显示JVM参数");
        System.out.println("  jps -v             显示传递给main的参数");
        System.out.println();
        
        System.out.println("示例输出:");
        System.out.println("  12345 MyApp");
        System.out.println("  23456 org.apache.catalina.startup.Bootstrap");
        System.out.println("  34567 sun.tools.jps.Jps");
        System.out.println();
    }
    
    private static void jstatDemo() {
        System.out.println("【jstat - 统计监控工具】\n");
        
        /*
        jstat [option vmid [interval[s|ms] [count]]]
        
        作用: 监控类加载、内存、GC等信息
        */
        
        System.out.println("常用选项:");
        System.out.println("  -class    类加载统计");
        System.out.println("  -gc       堆内存统计");
        System.out.println("  -gcutil   GC统计(百分比)");
        System.out.println("  -gccause  GC原因");
        System.out.println("  -gccapacity  堆内存容量");
        System.out.println("  -compiler JIT编译统计");
        System.out.println("  -printcompilation JIT编译方法");
        System.out.println();
        
        System.out.println("常用命令:");
        System.out.println("  jstat -gc 12345 1000 10   每秒打印GC信息,共10次");
        System.out.println("  jstat -gcutil 12345       打印GC使用率");
        System.out.println();
        
        System.out.println("输出示例 (jstat -gcutil 12345):");
        System.out.println("  S0    S1    E     O     M     CCS   YGC   YGCT   FGC   FGCT");
        System.out.println("  0.00 50.00 45.23 67.89 80.12 70.34  15   0.234   2    0.456");
        System.out.println();
        
        System.out.println("字段说明:");
        System.out.println("  S0, S1: Survivor使用率");
        System.out.println("  E: Eden使用率");
        System.out.println("  O: 老年代使用率");
        System.out.println("  M: 元空间使用率");
        System.out.println("  YGC: Young GC次数");
        System.out.println("  YGCT: Young GC时间");
        System.out.println("  FGC: Full GC次数");
        System.out.println("  FGCT: Full GC时间");
        System.out.println();
    }
    
    private static void jmapDemo() {
        System.out.println("【jmap - 内存映射工具】\n");
        
        /*
        jmap [option] vmid
        
        作用: 生成堆转储、查看内存信息
        */
        
        System.out.println("常用选项:");
        System.out.println("  -heap              打印堆摘要");
        System.out.println("  -histo             打印对象统计");
        System.out.println("  -histo:live        只统计存活对象(触发GC)");
        System.out.println("  -dump:format=b,file=heap.hprof  生成堆转储");
        System.out.println();
        
        System.out.println("常用命令:");
        System.out.println("  jmap -heap 12345               查看堆配置");
        System.out.println("  jmap -histo 12345              对象统计");
        System.out.println("  jmap -histo:live 12345         存活对象统计");
        System.out.println("  jmap -dump:format=b,file=heap.hprof 12345  堆转储");
        System.out.println();
        
        System.out.println("堆转储分析:");
        System.out.println("  1. 使用jvisualvm打开.hprof文件");
        System.out.println("  2. 使用MAT(Memory Analyzer Tool)分析");
        System.out.println("  3. 在线工具: https://heaphero.io");
        System.out.println();
    }
    
    private static void jstackDemo() {
        System.out.println("【jstack - 线程堆栈工具】\n");
        
        /*
        jstack [option] vmid
        
        作用: 打印线程堆栈,诊断死锁、性能问题
        */
        
        System.out.println("常用选项:");
        System.out.println("  -l    打印锁信息");
        System.out.println("  -m    打印本地方法帧");
        System.out.println("  -F    强制打印(无响应时)");
        System.out.println();
        
        System.out.println("常用命令:");
        System.out.println("  jstack 12345           打印线程堆栈");
        System.out.println("  jstack -l 12345        打印锁信息");
        System.out.println("  jstack 12345 > thread.txt  保存到文件");
        System.out.println();
        
        System.out.println("应用场景:");
        System.out.println("  1. CPU使用率高 - 找到占用CPU的线程");
        System.out.println("  2. 死锁检测 - 查看锁等待关系");
        System.out.println("  3. 线程阻塞 - 分析线程等待原因");
        System.out.println();
        
        System.out.println("CPU高使用率排查:");
        System.out.println("  1. top -H -p <pid>  找到占用CPU的线程");
        System.out.println("  2. printf '%x' <tid>  线程ID转16进制");
        System.out.println("  3. jstack <pid> | grep <hex-tid>  定位线程堆栈");
        System.out.println();
    }
    
    private static void jinfoDemo() {
        System.out.println("【jinfo - 配置信息工具】\n");
        
        /*
        jinfo [option] vmid
        
        作用: 查看和修改JVM参数
        */
        
        System.out.println("常用选项:");
        System.out.println("  -flags             打印所有JVM参数");
        System.out.println("  -flag <name>       打印指定参数");
        System.out.println("  -flag [+|-]<name>  开启/关闭参数");
        System.out.println("  -flag <name>=<val> 设置参数值");
        System.out.println();
        
        System.out.println("常用命令:");
        System.out.println("  jinfo -flags 12345              查看所有参数");
        System.out.println("  jinfo -flag MaxHeapSize 12345   查看堆大小");
        System.out.println("  jinfo -flag +PrintGC 12345      开启GC打印");
        System.out.println("  jinfo -flag MaxHeapFreeRatio=70 12345  设置参数");
        System.out.println();
        
        System.out.println("说明:");
        System.out.println("  - 部分参数可在运行时修改(Manageable)");
        System.out.println("  - jinfo -flags可查看哪些可修改");
        System.out.println();
    }
}
2.2.2 可视化工具
java 复制代码
/**
 * JVM可视化监控工具
 */
public class VisualToolsDemo {
    
    public static void main(String[] args) {
        System.out.println("=== JVM可视化监控工具 ===\n");
        
        jconsoleDemo();
        jvisualvmDemo();
        jmcDemo();
        thirdPartyTools();
    }
    
    private static void jconsoleDemo() {
        System.out.println("【JConsole】\n");
        
        /*
        JDK自带的监控工具
        启动命令: jconsole
        */
        
        System.out.println("功能:");
        System.out.println("  - 内存监控(堆、非堆、各内存池)");
        System.out.println("  - 线程监控(线程数、死锁检测)");
        System.out.println("  - 类加载监控");
        System.out.println("  - MBean浏览和操作");
        System.out.println("  - CPU使用率监控");
        System.out.println();
        
        System.out.println("使用场景:");
        System.out.println("  - 快速查看JVM状态");
        System.out.println("  - 内存使用趋势");
        System.out.println("  - 线程状态概览");
        System.out.println();
        
        System.out.println("启动:");
        System.out.println("  jconsole");
        System.out.println("  jconsole <pid>");
        System.out.println();
    }
    
    private static void jvisualvmDemo() {
        System.out.println("【JVisualVM】\n");
        
        /*
        JDK 8及之前自带
        JDK 11+需要单独下载: https://visualvm.github.io
        */
        
        System.out.println("功能:");
        System.out.println("  - 内存分析(堆转储、对象统计)");
        System.out.println("  - CPU分析(采样、跟踪)");
        System.out.println("  - 线程分析(线程转储、时间线)");
        System.out.println("  - GC可视化");
        System.out.println("  - 插件扩展(VisualGC、BTrace等)");
        System.out.println();
        
        System.out.println("常用操作:");
        System.out.println("  1. 监控 - 查看CPU、内存、线程实时数据");
        System.out.println("  2. 堆转储 - 捕获当前堆状态");
        System.out.println("  3. 分析堆转储 - 查找内存泄漏");
        System.out.println("  4. CPU采样 - 分析热点方法");
        System.out.println();
        
        System.out.println("内存泄漏分析步骤:");
        System.out.println("  1. 执行Heap Dump");
        System.out.println("  2. 查看Classes,找到实例数多的类");
        System.out.println("  3. 双击类查看实例");
        System.out.println("  4. 右键实例 -> Nearest GC Root");
        System.out.println("  5. 分析引用链,找到泄漏源");
        System.out.println();
        
        System.out.println("启动:");
        System.out.println("  jvisualvm (JDK 8)");
        System.out.println("  visualvm (JDK 11+,需单独安装)");
        System.out.println();
    }
    
    private static void jmcDemo() {
        System.out.println("【JMC - Java Mission Control】\n");
        
        /*
        Oracle官方工具,JDK 11+需要单独下载
        */
        
        System.out.println("功能:");
        System.out.println("  - JMX控制台监控");
        System.out.println("  - Java Flight Recorder (JFR) 分析");
        System.out.println("  - 低开销生产环境监控");
        System.out.println("  - 详细的事件分析");
        System.out.println();
        
        System.out.println("JFR (Java Flight Recorder):");
        System.out.println("  - 内置于JVM的低开销事件收集");
        System.out.println("  - 开销<1%,适合生产环境");
        System.out.println("  - 记录GC、编译、类加载、线程等事件");
        System.out.println();
        
        System.out.println("启用JFR:");
        System.out.println("  java -XX:+UnlockCommercialFeatures \\");
        System.out.println("       -XX:+FlightRecorder \\");
        System.out.println("       -XX:StartFlightRecording=duration=60s,filename=recording.jfr \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("下载:");
        System.out.println("  https://www.oracle.com/java/technologies/jdk-mission-control.html");
        System.out.println();
    }
    
    private static void thirdPartyTools() {
        System.out.println("【第三方工具】\n");
        
        System.out.println("1. MAT (Memory Analyzer Tool)");
        System.out.println("   - Eclipse项目,专业的堆转储分析");
        System.out.println("   - 内存泄漏检测、对象分析");
        System.out.println("   - 下载: https://eclipse.dev/mat/");
        System.out.println();
        
        System.out.println("2. GCEasy");
        System.out.println("   - 在线GC日志分析");
        System.out.println("   - 网址: https://gceasy.io");
        System.out.println("   - 自动分析GC问题并给出建议");
        System.out.println();
        
        System.out.println("3. GCViewer");
        System.out.println("   - 开源GC日志可视化");
        System.out.println("   - 下载: https://github.com/chewiebug/GCViewer");
        System.out.println();
        
        System.out.println("4. Arthas");
        System.out.println("   - 阿里开源的Java诊断工具");
        System.out.println("   - 在线诊断、无需重启");
        System.out.println("   - 功能: 监控、反编译、追踪等");
        System.out.println("   - 下载: https://arthas.aliyun.com");
        System.out.println();
        
        System.out.println("5. Perfino");
        System.out.println("   - 商业JVM监控工具");
        System.out.println("   - 企业级APM解决方案");
        System.out.println();
        
        System.out.println("6. YourKit");
        System.out.println("   - 商业Java性能分析器");
        System.out.println("   - CPU、内存、线程分析");
        System.out.println();
    }
}

2.3 性能问题排查

2.3.1 内存问题排查
java 复制代码
import java.util.*;
import java.lang.management.*;

/**
 * 内存问题排查示例
 */
public class MemoryIssueDemo {
    
    public static void main(String[] args) {
        System.out.println("=== 内存问题排查 ===\n");
        
        oomDiagnosis();
        memoryLeakDiagnosis();
        metaspaceOOMDiagnosis();
    }
    
    /**
     * OOM诊断
     */
    private static void oomDiagnosis() {
        System.out.println("【OOM诊断】\n");
        
        System.out.println("OOM类型及原因:");
        System.out.println();
        
        System.out.println("1. Java heap space");
        System.out.println("   原因: 堆内存不足或内存泄漏");
        System.out.println("   排查: jmap -histo, MAT分析堆转储");
        System.out.println("   解决: 增大-Xmx, 修复内存泄漏");
        System.out.println();
        
        System.out.println("2. Metaspace");
        System.out.println("   原因: 类加载过多或元空间设置过小");
        System.out.println("   排查: jstat -class, 检查类加载");
        System.out.println("   解决: 增大-XX:MaxMetaspaceSize");
        System.out.println();
        
        System.out.println("3. GC overhead limit exceeded");
        System.out.println("   原因: GC耗时过长但回收效果差");
        System.out.println("   排查: 分析GC日志");
        System.out.println("   解决: 增大堆内存, 优化对象创建");
        System.out.println();
        
        System.out.println("4. Direct buffer memory");
        System.out.println("   原因: NIO直接内存不足");
        System.out.println("   排查: 检查DirectByteBuffer使用");
        System.out.println("   解决: 增大-XX:MaxDirectMemorySize");
        System.out.println();
        
        System.out.println("5. unable to create new native thread");
        System.out.println("   原因: 线程数过多,系统资源不足");
        System.out.println("   排查: jstack, 检查线程数");
        System.out.println("   解决: 减少线程数, 增大系统限制");
        System.out.println();
        
        System.out.println("OOM排查步骤:");
        System.out.println("  1. 开启自动堆转储:");
        System.out.println("     -XX:+HeapDumpOnOutOfMemoryError");
        System.out.println("     -XX:HeapDumpPath=/path/to/dump");
        System.out.println("  2. 发生OOM后获取堆转储文件");
        System.out.println("  3. 使用MAT或JVisualVM分析");
        System.out.println("  4. 查找大对象和GC Root路径");
        System.out.println("  5. 定位泄漏代码并修复");
        System.out.println();
    }
    
    /**
     * 内存泄漏诊断
     */
    private static void memoryLeakDiagnosis() {
        System.out.println("【内存泄漏诊断】\n");
        
        System.out.println("内存泄漏常见场景:");
        System.out.println();
        
        System.out.println("1. 静态集合类引用");
        System.out.println("   示例: static Map<String, Object> cache");
        System.out.println("   问题: 只添加不删除");
        System.out.println("   解决: 使用弱引用(WeakHashMap)或定期清理");
        System.out.println();
        
        System.out.println("2. 监听器未注销");
        System.out.println("   示例: 注册事件监听器但未移除");
        System.out.println("   解决: 使用WeakReference或显式移除");
        System.out.println();
        
        System.out.println("3. ThreadLocal未清理");
        System.out.println("   示例: ThreadLocal在线程池场景");
        System.out.println("   解决: finally中调用remove()");
        System.out.println();
        
        System.out.println("4. 数据库/IO连接未关闭");
        System.out.println("   示例: JDBC Connection未close");
        System.out.println("   解决: try-with-resources");
        System.out.println();
        
        System.out.println("5. 缓存无限制增长");
        System.out.println("   示例: 无过期策略的缓存");
        System.out.println("   解决: 使用Caffeine/Guava Cache");
        System.out.println();
        
        System.out.println("诊断方法:");
        System.out.println("  1. 多次触发GC,观察内存是否持续增长");
        System.out.println("  2. 对比两次堆转储,找出增长的对象");
        System.out.println("  3. 分析GC Root,找到引用链");
        System.out.println("  4. 定位代码位置修复");
        System.out.println();
    }
    
    /**
     * 元空间OOM诊断
     */
    private static void metaspaceOOMDiagnosis() {
        System.out.println("【元空间OOM诊断】\n");
        
        System.out.println("原因分析:");
        System.out.println("  1. 加载类过多");
        System.out.println("  2. 动态代理/CGLib生成类");
        System.out.println("  3. JSP编译成类过多");
        System.out.println("  4. 反射使用过多");
        System.out.println();
        
        System.out.println("排查命令:");
        System.out.println("  jstat -class <pid>        查看类加载统计");
        System.out.println("  jmap -clstats <pid>       查看类加载器统计");
        System.out.println("  jcmd <pid> VM.classloader_stats  类加载器详情");
        System.out.println();
        
        System.out.println("解决方案:");
        System.out.println("  1. 增大元空间: -XX:MaxMetaspaceSize=512m");
        System.out.println("  2. 限制动态代理生成: sun.misc.ProxyGenerator.saveGeneratedFiles");
        System.out.println("  3. 优化JSP,减少类生成");
        System.out.println("  4. 检查类加载器泄漏");
        System.out.println();
    }
}
2.3.2 CPU问题排查
java 复制代码
import java.util.*;

/**
 * CPU问题排查示例
 */
public class CPUIssueDemo {
    
    public static void main(String[] args) {
        System.out.println("=== CPU问题排查 ===\n");
        
        highCPUDiagnosis();
        threadBlockDiagnosis();
        deadlockDiagnosis();
    }
    
    /**
     * CPU使用率高排查
     */
    private static void highCPUDiagnosis() {
        System.out.println("【CPU使用率高排查】\n");
        
        System.out.println("排查步骤:");
        System.out.println();
        
        System.out.println("Step 1: 找到高CPU进程");
        System.out.println("  top");
        System.out.println("  ps aux | grep java");
        System.out.println();
        
        System.out.println("Step 2: 找到高CPU线程");
        System.out.println("  top -H -p <pid>");
        System.out.println("  # 查看进程下的线程CPU使用率");
        System.out.println();
        
        System.out.println("Step 3: 线程ID转16进制");
        System.out.println("  printf '%x' <tid>");
        System.out.println("  # 例如: printf '%x' 12345 -> 3039");
        System.out.println();
        
        System.out.println("Step 4: 定位线程堆栈");
        System.out.println("  jstack <pid> | grep <hex-tid>");
        System.out.println("  jstack <pid> | grep -A 20 3039");
        System.out.println();
        
        System.out.println("完整示例:");
        System.out.println("  # 1. 找到Java进程PID");
        System.out.println("  jps");
        System.out.println("  # 假设PID是 12345");
        System.out.println();
        System.out.println("  # 2. 找到高CPU线程");
        System.out.println("  top -H -p 12345");
        System.out.println("  # 假设线程TID是 12350");
        System.out.println();
        System.out.println("  # 3. 转换TID为16进制");
        System.out.println("  printf '%x' 12350");
        System.out.println("  # 输出: 303e");
        System.out.println();
        System.out.println("  # 4. 查看线程堆栈");
        System.out.println("  jstack 12345 | grep -A 20 303e");
        System.out.println();
        
        System.out.println("常见原因:");
        System.out.println("  1. 死循环");
        System.out.println("  2. 频繁GC");
        System.out.println("  3. 正则表达式回溯");
        System.out.println("  4. 加密算法计算量大");
        System.out.println("  5. 序列化/反序列化");
        System.out.println();
    }
    
    /**
     * 线程阻塞排查
     */
    private static void threadBlockDiagnosis() {
        System.out.println("【线程阻塞排查】\n");
        
        System.out.println("查看线程状态:");
        System.out.println("  jstack <pid>");
        System.out.println();
        
        System.out.println("线程状态说明:");
        System.out.println("  NEW          新建");
        System.out.println("  RUNNABLE     运行中");
        System.out.println("  BLOCKED      阻塞(等待锁)");
        System.out.println("  WAITING      等待(无限期)");
        System.out.println("  TIMED_WAITING 超时等待");
        System.out.println("  TERMINATED   终止");
        System.out.println();
        
        System.out.println("常见阻塞原因:");
        System.out.println("  1. 等待锁 - synchronized");
        System.out.println("  2. 等待IO - 网络、文件");
        System.out.println("  3. 等待通知 - wait/notify");
        System.out.println("  4. 等待条件 - Condition.await");
        System.out.println("  5. 等待任务 - Future.get");
        System.out.println("  6. 睡眠 - Thread.sleep");
        System.out.println();
        
        System.out.println("jstack输出示例:");
        System.out.println("""
  "thread-1" prio=5 tid=0x... nid=0x... waiting for monitor entry
    java.lang.Thread.State: BLOCKED (on object monitor)
      at com.example.MyClass.method(MyClass.java:100)
      - waiting to lock <0x...> (a java.lang.Object)
      - locked <0x...> (a java.lang.Object)
      ...
        """);
        System.out.println();
    }
    
    /**
     * 死锁排查
     */
    private static void deadlockDiagnosis() {
        System.out.println("【死锁排查】\n");
        
        System.out.println("死锁检测:");
        System.out.println("  jstack -l <pid>");
        System.out.println("  # 会自动检测死锁并打印");
        System.out.println();
        
        System.out.println("死锁输出示例:");
        System.out.println("""
  Found one Java-level deadlock:
  =============================
  "thread-1":
    waiting to lock monitor 0x... (object 0x..., a java.lang.Object),
    which is held by "thread-2"
  "thread-2":
    waiting to lock monitor 0x... (object 0x..., a java.lang.Object),
    which is held by "thread-1"
  
  Java stack information for the threads listed above:
  ===================================================
  "thread-1":
      at com.example.DeadlockDemo.run(DeadlockDemo.java:20)
      - waiting to lock <0x...> (a java.lang.Object)
      - locked <0x...> (a java.lang.Object)
  "thread-2":
      at com.example.DeadlockDemo.run(DeadlockDemo.java:30)
      - waiting to lock <0x...> (a java.lang.Object)
      - locked <0x...> (a java.lang.Object)
  
  Found 1 deadlock.
        """);
        System.out.println();
        
        System.out.println("死锁预防:");
        System.out.println("  1. 固定加锁顺序");
        System.out.println("  2. 使用tryLock超时");
        System.out.println("  3. 使用Lock代替synchronized");
        System.out.println("  4. 减小锁粒度");
        System.out.println("  5. 使用无锁数据结构");
        System.out.println();
    }
}

2.4 调优实践案例

java 复制代码
/**
 * 调优实践案例
 */
public class TuningCaseDemo {
    
    public static void main(String[] args) {
        System.out.println("=== 调优实践案例 ===\n");
        
        case1_HighThroughput();
        case2_LowLatency();
        case3_BigHeap();
        case4_Microservice();
    }
    
    /**
     * 案例1: 批处理应用 - 高吞吐量
     */
    private static void case1_HighThroughput() {
        System.out.println("【案例1: 批处理应用 - 高吞吐量】\n");
        
        System.out.println("场景特点:");
        System.out.println("  - 离线数据处理");
        System.out.println("  - 关注吞吐量");
        System.out.println("  - 可接受较长GC停顿");
        System.out.println();
        
        System.out.println("调优目标:");
        System.out.println("  - 最大化吞吐量");
        System.out.println("  - 减少GC总时间占比");
        System.out.println();
        
        System.out.println("推荐配置:");
        System.out.println("  java -Xms8g -Xmx8g \\");
        System.out.println("       -XX:+UseParallelGC \\");
        System.out.println("       -XX:NewRatio=1 \\");
        System.out.println("       -XX:SurvivorRatio=6 \\");
        System.out.println("       -XX:MaxTenuringThreshold=10 \\");
        System.out.println("       -XX:ParallelGCThreads=8 \\");
        System.out.println("       -XX:GCTimeRatio=19 \\");
        System.out.println("       -XX:MaxGCPauseMillis=500 \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("配置说明:");
        System.out.println("  - UseParallelGC: 吞吐量优先收集器");
        System.out.println("  - NewRatio=1: 新生代占一半(对象存活率高)");
        System.out.println("  - GCTimeRatio=19: 目标吞吐量95%");
        System.out.println("  - MaxGCPauseMillis=500: 允许较长停顿");
        System.out.println();
    }
    
    /**
     * 案例2: Web应用 - 低延迟
     */
    private static void case2_LowLatency() {
        System.out.println("【案例2: Web应用 - 低延迟】\n");
        
        System.out.println("场景特点:");
        System.out.println("  - 在线服务");
        System.out.println("  - 关注响应时间");
        System.out.println("  - 要求低GC停顿");
        System.out.println();
        
        System.out.println("调优目标:");
        System.out.println("  - GC停顿 < 100ms");
        System.out.println("  - 避免Full GC");
        System.out.println();
        
        System.out.println("推荐配置 (G1 GC):");
        System.out.println("  java -Xms4g -Xmx4g \\");
        System.out.println("       -XX:+UseG1GC \\");
        System.out.println("       -XX:MaxGCPauseMillis=100 \\");
        System.out.println("       -XX:G1HeapRegionSize=8m \\");
        System.out.println("       -XX:InitiatingHeapOccupancyPercent=35 \\");
        System.out.println("       -XX:G1ReservePercent=20 \\");
        System.out.println("       -XX:+ExplicitGCInvokesConcurrent \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("推荐配置 (ZGC):");
        System.out.println("  java -Xms4g -Xmx4g \\");
        System.out.println("       -XX:+UseZGC \\");
        System.out.println("       -XX:ConcGCThreads=2 \\");
        System.out.println("       -XX:ZCollectionInterval=5 \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("配置说明:");
        System.out.println("  - UseG1GC: 延迟优先收集器");
        System.out.println("  - MaxGCPauseMillis=100: 控制停顿时间");
        System.out.println("  - InitiatingHeapOccupancyPercent=35: 提前触发Mixed GC");
        System.out.println();
    }
    
    /**
     * 案例3: 大内存应用
     */
    private static void case3_BigHeap() {
        System.out.println("【案例3: 大内存应用】\n");
        
        System.out.println("场景特点:");
        System.out.println("  - 堆内存 > 16GB");
        System.out.println("  - 缓存型应用");
        System.out.println("  - 长时间运行");
        System.out.println();
        
        System.out.println("推荐配置:");
        System.out.println("  java -Xms32g -Xmx32g \\");
        System.out.println("       -XX:+UseZGC \\");
        System.out.println("       -XX:+ZGenerational \\");
        System.out.println("       -XX:ConcGCThreads=4 \\");
        System.out.println("       -XX:ZCollectionInterval=10 \\");
        System.out.println("       -XX:ZAllocationSpikeTolerance=4 \\");
        System.out.println("       -XX:+UnlockExperimentalVMOptions \\");
        System.out.println("       -XX:+UseTransparentHugePages \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("配置说明:");
        System.out.println("  - UseZGC: 支持大堆、低延迟");
        System.out.println("  - ZGenerational: 分代ZGC (JDK 21+)");
        System.out.println("  - UseTransparentHugePages: 使用大页内存");
        System.out.println();
    }
    
    /**
     * 案例4: 微服务应用
     */
    private static void case4_Microservice() {
        System.out.println("【案例4: 微服务应用】\n");
        
        System.out.println("场景特点:");
        System.out.println("  - 容器化部署");
        System.out.println("  - 内存有限(2-4GB)");
        System.out.println("  - 多实例运行");
        System.out.println();
        
        System.out.println("推荐配置:");
        System.out.println("  java -Xms1536m -Xmx1536m \\");
        System.out.println("       -XX:+UseG1GC \\");
        System.out.println("       -XX:MaxGCPauseMillis=50 \\");
        System.out.println("       -XX:G1HeapRegionSize=4m \\");
        System.out.println("       -XX:InitiatingHeapOccupancyPercent=30 \\");
        System.out.println("       -XX:MaxMetaspaceSize=256m \\");
        System.out.println("       -XX:CompressedClassSpaceSize=128m \\");
        System.out.println("       -XX:+UseStringDeduplication \\");
        System.out.println("       -Xss512k \\");
        System.out.println("       -XX:+UseContainerSupport \\");
        System.out.println("       -XX:MaxRAMPercentage=75.0 \\");
        System.out.println("       -jar app.jar");
        System.out.println();
        
        System.out.println("配置说明:");
        System.out.println("  - UseContainerSupport: 自动感知容器内存限制");
        System.out.println("  - MaxRAMPercentage: 使用容器内存的百分比");
        System.out.println("  - UseStringDeduplication: 字符串去重减少内存");
        System.out.println("  - Xss512k: 减小线程栈节省内存");
        System.out.println();
    }
}

三、总结与最佳实践

调优流程

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                       JVM调优标准流程                                │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. 明确目标                                                        │
│     ↓                                                              │
│  2. 收集数据    (监控工具、GC日志)                                   │
│     ↓                                                              │
│  3. 分析问题    (内存、CPU、GC)                                     │
│     ↓                                                              │
│  4. 制定方案    (调整参数、优化代码)                                 │
│     ↓                                                              │
│  5. 实施调优    (每次只改一个参数)                                   │
│     ↓                                                              │
│  6. 验证效果    (压测、对比)                                        │
│     ↓                                                              │
│  7. 持续监控    (生产环境观察)                                       │
│     ↓                                                              │
│  8. 循环迭代                                                        │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

调优检查清单

markdown 复制代码
## JVM调优检查清单

### 启动参数
- [ ] -Xms和-Xmx设置为相同值
- [ ] 选择合适的GC收集器
- [ ] 开启GC日志
- [ ] 设置合理的元空间大小

### 内存配置
- [ ] 堆内存 ≤ 物理内存的80%
- [ ] 新生代比例合适(根据对象存活率)
- [ ] 元空间有上限
- [ ] 直接内存有上限(如使用NIO)

### GC配置
- [ ] GC停顿时间目标合理
- [ ] 吞吐量目标合理
- [ ] 大对象阈值合适
- [ ] 晋升年龄阈值合适

### 监控
- [ ] GC日志保留
- [ ] 堆转储机制(OOM时自动dump)
- [ ] 监控告警(内存、CPU、GC)
- [ ] 性能基线数据

### 代码层面
- [ ] 避免大对象频繁创建
- [ ] 避免内存泄漏
- [ ] 合理使用缓存
- [ ] 线程池配置合理

常用调优命令速查

bash 复制代码
# 查看Java进程
jps -l

# 查看GC统计
jstat -gcutil <pid> 1000

# 生成堆转储
jmap -dump:format=b,file=heap.hprof <pid>

# 查看线程堆栈
jstack <pid> > thread.txt

# 查看JVM参数
jinfo -flags <pid>

# 查看类加载
jstat -class <pid>

# CPU高使用率排查
top -H -p <pid>
printf '%x' <tid>
jstack <pid> | grep <hex-tid>

# 强制GC
jcmd <pid> GC.run

最佳实践总结

  1. 不要过早优化 - 先保证功能正确
  2. 基于数据调优 - 使用监控数据指导
  3. 逐步调整 - 每次只改一个参数
  4. 生产验证 - 压测环境验证后再上生产
  5. 持续监控 - 调优后持续观察效果

相关资源

相关推荐
SEO-狼术2 小时前
PDFs Programmatically in WPF
java·.net
2401_878530212 小时前
深入理解Python的if __name__ == ‘__main__‘
jvm·数据库·python
逝水如流年轻往返染尘2 小时前
JAVA中的内部类
java·开发语言
深蓝轨迹2 小时前
黑马点评--达人探店模块
java·spring boot·redis
!停2 小时前
C++入门基础—类和对象3
java·数据库·c++
寂静or沉默2 小时前
Java程序员技术面试:如何清晰描述项目难点?逻辑模板!Java的原因与解决方案最新发布!
java·开发语言·面试
庞轩px2 小时前
模拟面试回答第十四问:双亲委派模型
jvm·面试·职场和发展·tomcat·类加载·类加载器·双亲委派模型
llilian_162 小时前
ptp从时钟 ptp授时模块 如何挑选PTP从时钟授时协议模块 ptp从时钟模块
数据库·功能测试·单片机·嵌入式硬件·测试工具
东离与糖宝3 小时前
Gradle 9.4+Java26:大型项目构建提速100倍实战配置
java·人工智能