tomcat内存溢出问题本质是jvm堆内存不足导致“java heap space”错误,需通过合理设置-xms/-xmx、优化新生代比例、选用g1gc等垃圾收集器、排查内存泄漏并配合监控工具进行系统性调优。

Apache 本身不直接执行 Java 字节码,它处理动态内容(如 JSP、Servlet)通常依赖于后端应用服务器,比如 Tomcat。所以当你说“Apache 处理动态内容时内存溢出”,实际问题往往出在 Apache 与 Tomcat 的集成场景中(如通过 mod_jk 或 mod_proxy_ajp),或者你混淆了 Apache HTTP Server 和 Apache Tomcat —— 后者才是 Java Web 应用的运行容器,也是内存溢出(OutOfMemoryError)的真正发生地。
下面分几种典型情况,给出针对性解决路径:
明确责任主体:是 Apache 还是 Tomcat 在耗内存?
- 如果你用的是 纯 Apache + PHP/Python/Perl:内存溢出多由脚本语言自身或扩展模块引起(如 PHP 的 memory_limit 不足、未释放大数组、循环引用等),和 JVM 无关。
- 如果你用的是 Apache + Tomcat(反向代理或 AJP 连接):绝大多数“动态内容内存溢出”实际发生在 Tomcat 的 JVM 堆中,Apache 只是前端转发器,本身内存占用极小(除非 mod_php/mod_perl 配置不当)。
- 如果你误把 Tomcat 当作 Apache:那所有调优都应在 Tomcat 的 JVM 参数和应用代码层面展开。
确认方式:
查看错误日志中是否出现 java.lang.OutOfMemoryError —— 出现即为 Tomcat/JVM 问题;
若出现 Cannot allocate memory、Segmentation fault 或 Apache worker process crash,则需查 Apache 自身配置或模块兼容性。
Tomcat 侧:JVM 堆内存不足(最常见)
这是生产环境 80% 以上“内存溢出”的根源,表现为:
java.lang.OutOfMemoryError: Java heap space
关键动作:
-
在
bin/catalina.sh(Linux)或bin/catalina.bat(Windows)中设置稳定且合理的 JVM 参数:export CATALINA_OPTS="-server -Xms4g -Xmx4g -Xmn1g -XX:SurvivorRatio=8 -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/tomcat/heapdump.hprof"
-
-Xms和-Xmx设为相同值,避免堆动态扩容带来的 GC 波动; -
-Xmn控制年轻代大小(建议为-Xmx的 25%~33%); -
UseG1GC更适合大堆(≥4GB)和低延迟要求场景; -
HeapDumpOnOutOfMemoryError确保崩溃时自动生成 dump 文件用于分析。
-
-
避免使用已废弃的
PermGen参数(JDK 8+ 已被 Metaspace 替代):- ❌ 错误写法:
-XX:MaxPermSize=256m - ✅ 正确写法(JDK 8+):
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
- ❌ 错误写法:
Tomcat 侧:类加载泄漏(尤其热部署/频繁重启)
表现为:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
java.lang.OutOfMemoryError: Metaspace
原因通常是:
- 应用频繁 redeploy(如开发阶段用 IDE 热部署);
- 第三方库(如 JDBC 驱动、日志框架)注册了静态监听器但未清理;
-
ServletContextListener中启动线程未正确关闭; - 使用
ThreadLocal未remove(),导致 classloader 无法卸载。
解决建议:
- 生产环境禁用自动热部署(删掉
conf/Catalina/localhost/*.xml中的 reloadable="true"); - 检查
web.xml或注解中是否有未关闭的定时任务、线程池、数据库连接池; - 使用 MAT 分析 heap dump 中的
ClassLoader实例数和java.lang.Class占比; - 统一使用
try-with-resources或显式close()管理资源。
Apache 侧:Worker 进程内存失控(较少见但需排查)
仅当 Apache 直接运行 CGI/PHP 且配置激进时可能发生:
-
检查
MPM模块类型(prefork vs event):- prefork:每个请求一个进程,
MaxRequestWorkers过高易耗尽内存; - event:基于线程,更省内存,但需确保模块线程安全(如
mod_php不支持 event)。
- prefork:每个请求一个进程,
-
调整关键参数(以 prefork 为例):
<ifmodule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 150 # 总并发数,按每个 PHP 进程约 30–50MB 估算 MaxConnectionsPerChild 10000 </ifmodule> -
对 PHP 应用,检查
php.ini:memory_limit = 128M # 避免单请求吃光全部内存 max_execution_time = 30
快速验证与持续监控
- 实时观察:
jstat -gc <pid></pid>查看 GC 频率与堆使用趋势; - 日志开关:在
logging.properties中启用org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = FINE; - 推荐轻量工具:
jconsole(JDK 自带)、VisualVM(免费)、或 Prometheus + JMX Exporter 做长期指标采集。
不复杂但容易忽略——很多问题不是缺内存,而是对象没释放、配置没生效、或 dump 没分析到位。










