本文目录导读:

我将为您系统性地介绍Java问题排查的实战案例,从常见问题到具体排查方法,每个案例都包含详细的诊断思路和解决方案。
CPU使用率过高排查
案例1:CPU飙升至100%
问题现象:应用响应缓慢,CPU使用率持续在100%
排查步骤:
找到CPU最高的进程
# 查看所有Java进程CPU使用率 top -c # 或使用更详细的查看方式 ps -eo pid,ppid,%mem,%cpu,cmd --sort=-%cpu | head -20
定位到问题的线程
# 找到CPU使用最高的线程 top -Hp <PID> # 查看线程信息 ps -mp <PID> -o THREAD,tid,time
将线程ID转换为十六进制
printf "%x\n" <TID>
导出线程栈信息
jstack <PID> > thread_dump.txt # 在dump文件中查找对应线程 grep -A 30 "0x<十六进制TID>" thread_dump.txt
常见原因和解决方案:
- 死循环
// 问题代码示例 while(true) { // 业务逻辑 }
// 排查方法:线程栈会显示在一个方法内反复执行
2. **频繁GC导致CPU飙升**
```bash
# 查看GC情况
jstat -gcutil <PID> 1000 10
- 正则表达式回溯
// 危险的正则表达式导致CPU高 String pattern = "(a+)+$";
内存溢出(OOM)排查
案例2:Java堆内存溢出
问题现象:报错java.lang.OutOfMemoryError: Java heap space
排查步骤:
启动时添加参数
java -Xms512m -Xmx512m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump/
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/path/to/gc.log
使用MAT分析堆转储文件
# 下载并打开堆转储文件 jhat <heap-dump-file> # 或使用Eclipse MAT # File -> Open Heap Dump
典型OOM场景分析
内存泄漏示例:
public class MemoryLeak {
private static List<byte[]> LEAK = new ArrayList<>();
public void leak() {
while(true) {
byte[] bytes = new byte[1024 * 1024]; // 1MB
LEAK.add(bytes); // 永远不会被回收
}
}
}
解决方案:
- 使用
-Xmx参数调整堆大小 - 优化代码,减少内存占用
- 使用缓存时设置合理的过期策略
- 使用
-XX:+UseG1GC等垃圾回收器优化
案例3:Metaspace溢出
问题现象:java.lang.OutOfMemoryError: Metaspace
原因分析:
- 动态生成大量类
- 使用cglib/ASM等字节码技术
- 不正确的类加载器使用
解决方案:
# 调整Metaspace大小 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
死锁排查
案例4:多线程死锁
问题现象:程序卡住,无响应
排查步骤:
获取线程dump
jstack <PID> > thread_dump.txt
查找死锁信息
# 在dump文件中查找明显标记 grep -A 20 "Found one Java-level deadlock" thread_dump.txt
死锁示例:
public class DeadlockExample {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread1 acquired lock1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread1 acquired lock2");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread2 acquired lock2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("Thread2 acquired lock1");
}
}
});
t1.start();
t2.start();
}
}
解决方案:
- 使用定时锁
tryLock()避免死锁 - 保持锁顺序一致性
- 使用并发工具类如
ReentrantLock
数据库连接池耗尽
案例5:连接池连接无法释放
问题现象:报错Cannot get a connection, pool exhausted
排查步骤:
检查连接池配置
# Spring Boot配置示例
spring:
datasource:
hikari:
maximum-pool-size: 50
connection-timeout: 30000
leak-detection-threshold: 60000
启用连接泄漏检测
// HikariCP配置
HikariConfig config = new HikariConfig();
config.setLeakDetectionThreshold(60000); // 60秒
config.setPoolName("MyPool");
检查代码模式
// 错误示例 - 连接未关闭
public void badQuery() throws SQLException {
Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 忘记关闭连接!
}
// 正确示例 - 使用try-with-resources
public void goodQuery() throws SQLException {
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
// 处理结果
}
}
线程池问题排查
案例6:线程池拒绝策略
问题现象:报错RejectedExecutionException
排查步骤:
检查线程池状态
# 使用jstack查看线程池状态 jstack <PID> | grep -A 10 "ThreadPoolExecutor"
分析代码
// 问题代码示例
ExecutorService executor = Executors.newFixedThreadPool(10);
// 任务提交速度过快,队列满了
// 解决方案:选择适当的拒绝策略
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
60, TimeUnit.SECONDS, // 空闲线程存活时间
new ArrayBlockingQueue<>(100), // 队列容量
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
性能瓶颈分析
案例7:频繁Full GC
问题现象:大量Full GC,应用卡顿
排查步骤:
查看GC日志
jstat -gcutil <PID> 1000 # 或查看GC日志文件 grep "Full GC" gc.log
使用VisualVM/JMC分析
# 使用jcmd查看GC信息 jcmd <PID> GC.heap_info jcmd <PID> VM.native_memory
优化方案
# G1收集器优化示例 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -Xmx4g
完整排查工具集
JDK自带工具
jps # 查看Java进程 jstat # 查看JVM统计信息 jstack # 线程转储 jmap # 内存映射 jhat # 堆分析工具 jcmd # JVM命令工具 jinfo # JVM配置信息
常用命令示例
# 查看JVM参数 jcmd <PID> VM.print_compilation # 查看GC配置 jcmd <PID> GC.class_histogram # 导出堆快照 jmap -dump:format=b,file=heap.hprof <PID> # 查看线程状态分布 jstack <PID> | grep "java.lang.Thread.State" | sort | uniq -c
排查脚本示例
#!/bin/bash # auto_diagnose.sh PID=$1 echo "=== 1. System Load ===" top -b -n 1 | head -5 echo "=== 2. Memory Usage ===" free -m echo "=== 3. Java Process Info ===" jcmd $PID VM.version jcmd $PID VM.flags echo "=== 4. Thread Dump ===" jstack $PID > thread_dump.txt echo "=== 5. Heap Summary ===" jmap -heap $PID echo "=== 6. GC Statistics ===" jstat -gcutil $PID 1000 5
最佳实践建议
预防措施
- 开发环境启用
-Xmx,-Xms调优 - 生产环境启用GC日志和HeapDumpOnOutOfMemoryError
- 使用APM工具监控(如SkyWalking, Zipkin)
监控告警
# Prometheus + Grafana监控配置示例
- job_name: 'jvm'
static_configs:
- targets: ['localhost:8080']
metrics_path: '/actuator/prometheus'
常见错误处理清单
| 症状 | 可能原因 | 排查方法 |
|---|---|---|
| CPU高 | 死循环、GC频繁 | jstack + jstat |
| 内存溢出 | OOM、内存泄漏 | jmap + MAT |
| 响应慢 | 网络、IO、锁竞争 | jstack + JMC |
| 连接耗尽 | 连接不释放、配置不当 | 连接池监控 |
通过这些案例和工具的使用,您可以系统地排查Java应用中的各种问题,好的监控和日志是有效排查的基础。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播