# Tomcat 服务频繁崩溃排查方法
当Tomcat服务频繁崩溃时,可以按照以下步骤进行系统化排查:
## 1. 检查日志文件
**关键日志位置**:
- `catalina.out` (标准输出和错误)
- `catalina.log` (主日志)
- `localhost.log` (应用相关日志)
- `host-manager.log` 和 `manager.log` (管理相关日志)
**重点关注**:
- 崩溃前的错误堆栈(Stack Trace)
- OutOfMemoryError 或其他内存相关错误
- 线程死锁(Deadlock)信息
- 频繁的GC日志
## 2. 内存问题排查
**常见内存问题**:
- 堆内存溢出(Java heap space)
- 永久代/元空间溢出(PermGen/Metaspace)
- 栈溢出(StackOverflowError)
- 直接内存溢出(Direct buffer memory)
**排查工具**:
- 在启动脚本中添加JVM参数:
```
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof
```
- 使用`jmap`生成堆转储:
```bash
jmap -dump:format=b,file=/path/to/dump.hprof <pid>
```
- 使用`jstat`监控内存使用:
```bash
jstat -gcutil <pid> 1000
```
## 3. 线程问题排查
**检查线程状态**:
```bash
jstack <pid> > thread_dump.txt
```
分析线程转储文件,查找:
- 死锁(deadlock)
- 大量线程阻塞(blocked)
- 线程卡在相同代码位置
## 4. 资源泄漏检查
**常见泄漏源**:
- 数据库连接未关闭
- 文件流未关闭
- 静态集合持续增长
- 缓存未设置上限
**排查方法**:
- 使用`jmap -histo:live <pid>`查看对象分布
- 使用VisualVM或MAT分析堆转储
## 5. 系统资源检查
```bash
# 检查系统内存
free -m
# 检查打开文件限制
ulimit -a
# 检查进程资源使用
top -p <pid>
```
## 6. 配置检查
**关键配置项**:
- `server.xml`中的连接器(Connector)配置
- 线程池配置
- JVM内存参数(Xms, Xmx, PermSize/MetaspaceSize)
- 检查是否有过多的web应用部署
## 7. 监控工具
- **VisualVM**:图形化监控JVM状态
- **JConsole**:JMX监控工具
- **Prometheus + Grafana**:建立长期监控
- **APM工具**:如SkyWalking, Pinpoint等
## 8. 常见解决方案
1. **内存不足**:
- 增加JVM堆大小(-Xms, -Xmx)
- 调整新生代/老年代比例(-XX:NewRatio)
- 增加元空间大小(-XX:MetaspaceSize)
2. **线程问题**:
- 调整线程池大小(maxThreads)
- 优化代码避免死锁
- 减少同步块范围
3. **资源泄漏**:
- 确保所有资源正确关闭
- 使用try-with-resources语句
- 限制缓存大小
4. **系统限制**:
- 增加最大文件描述符数
- 调整系统内核参数
## 9. 高级排查
对于难以复现的问题:
- 启用飞行记录(JFR):`-XX:+FlightRecorder`
- 使用async-profiler进行性能分析
- 考虑使用商业分析工具如YourKit
通过以上系统化排查,通常可以定位到Tomcat频繁崩溃的根本原因。