Linux下Tomcat内存溢出怎么办
小樊
44
2025-12-05 00:28:50
Linux下Tomcat内存溢出定位与处理
一、快速判断异常类型
- 查看 catalina.out 或 localhost.<日期>.log 中的异常关键字,常见三类:
- Java heap space:堆内存不足,通常是对象申请过多且未及时释放。
- PermGen space / Metaspace:类元数据区不足,常见于应用热部署频繁、第三方 jar 多或版本冲突。
- unable to create new native thread:系统无法再创建线程,多与系统/容器内存与线程栈配置相关。
二、对应处理方案
- 堆内存不足(Java heap space)
- 调整堆大小:设置 -Xms 与 -Xmx(建议等值,如 -Xms2g -Xmx2g),并结合 -Xmn(常取 -Xmx 的 1/4)优化新生代;总堆一般不超过物理内存的 80%。示例:JAVA_OPTS=“-Xms2g -Xmx2g -Xmn512m”。
- 元空间不足(PermGen/Metaspace)
- Java 7 及更早:增大 -XX:PermSize 与 -XX:MaxPermSize(如 -XX:PermSize=256m -XX:MaxPermSize=512m)。
- Java 8 及以后:使用 -XX:MetaspaceSize 与 -XX:MaxMetaspaceSize(如 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m),避免无限制增长。
- 无法创建新线程(unable to create new native thread)
- 估算最大线程数:线程上限 ≈ (MaxProcessMemory − JVMMemory − ReservedOsMemory) / ThreadStackSize。例如 32 位进程可用约 2GB、JVM 占用 1.5GB、系统保留 120MB、默认线程栈 1MB/线程,则上限约 380 线程;可通过降低 -Xmx、减小 -Xss、或增加系统可用内存来提升上限。
- 系统资源与容器配置
- 检查 ulimit -a(如 open files、max user processes),必要时调大;排查应用是否打开过多文件句柄或创建过多线程。
三、在Linux中修改Tomcat内存参数
- 编辑 $CATALINA_HOME/bin/catalina.sh,在 cygwin=false 这一行之前添加 JAVA_OPTS(注意引号为英文双引号):
- Java 7 示例:
- JAVA_OPTS=“-Xms1024m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m”
- Java 8+ 示例:
- JAVA_OPTS=“-Xms1024m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m”
- 如使用服务方式启动,需按服务脚本/工具(如 systemd 单元或 Tomcat 自带服务包装器)的文档设置 JAVA_OPTS 或相应服务参数,避免仅修改 catalina.sh 不生效。
四、验证与监控
- 重启后在日志中确认参数已生效(如 ps -ef | grep tomcat 能看到带 -Xms/-Xmx 的 Java 进程),并观察 catalina.out 是否仍有 OOM。
- 打开 GC 日志以辅助分析:添加 -verbose:gc -Xloggc:gc.log,必要时配合可视化工具(如 jvisualvm)或堆转储分析(如 Eclipse MAT)定位大对象与泄漏根因。
五、常见陷阱与优化建议
- 将 -Xms 与 -Xmx 设为相同,减少运行时扩缩堆带来的抖动;-Xmn 常取 -Xmx 的 1/4,其余留给老年代。
- 减少 jar 冲突/重复:将通用第三方 jar 放到 tomcat/shared/lib(适用于多应用共享场景),降低 PermGen/Metaspace 压力。
- 控制线程与连接:避免线程泄漏与连接泄漏;必要时优化 Connector/Executor 线程池配置,减少不必要的线程创建。