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

JVM调优详解

一、知识概述

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

调优目标

scss 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                       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();
    }
}

三、总结与最佳实践

调优流程

scss 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                       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. 持续监控 - 调优后持续观察效果

相关资源

相关推荐
llz_1122 小时前
web-第二次课后作业
前端·后端·web
红尘散仙8 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记10 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆10 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪10 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball61611 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_25183645711 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao11 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒12 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰13 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理