Tomcat日志中内存溢出的解决方案
首先需要通过日志和工具定位内存溢出的具体类型(如堆内存、元空间、栈内存或线程溢出)。查看Tomcat日志(catalina.out、localhost.log)中的OutOfMemoryError信息,例如“Java heap space”表示堆内存不足,“PermGen space”(Java 7及之前)或“Metaspace”(Java 8+)表示元空间不足,“StackOverflowError”表示栈内存溢出。同时,使用JVM监控工具(如jconsole、jvisualvm、YourKit)监控内存使用趋势,分析是突发峰值还是持续增长导致的内存耗尽。
根据诊断结果调整Tomcat的JVM启动参数,合理分配内存空间:
-Xms(初始堆大小)和-Xmx(最大堆大小)调整堆内存,建议两者设置为相同值(避免堆内存动态扩展带来的性能损耗),例如-Xms1024m -Xmx2048m(根据服务器物理内存调整,一般不超过物理内存的1/4)。-XX:MetaspaceSize(初始元空间大小)和-XX:MaxMetaspaceSize(最大元空间大小),例如-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m(适用于动态生成大量类的应用,如使用JSP或频繁加载类的场景)。StackOverflowError,调整-Xss参数(每个线程的栈大小),例如-Xss2m(默认1MB,可根据应用递归深度适当增大,但不宜超过10MB,否则会占用过多内存)。代码中的内存泄漏或不规范操作是内存溢出的常见原因,需重点排查:
Eclipse MAT、VisualVM)检测内存中的对象引用链,修复未释放的对象(如静态集合类长期持有对象引用、未关闭的数据库连接/文件流、监听器未注销等)。String对象,可使用StringBuilder替代),重用对象(如数据库连接池、线程池)。SELECT * FROM large_table),使用分页查询(LIMIT语句)或延迟加载,减少内存中的数据量。合理的垃圾回收(GC)配置可提升内存回收效率,减少内存溢出风险:
-XX:+UseG1GC(适用于大内存、低延迟场景,Java 9+默认)、-XX:+UseConcMarkSweepGC(适用于多核服务器,低停顿要求)。-XX:CMSInitiatingOccupancyFraction=70(CMS收集器在老年代占用70%时触发回收)、-XX:MaxGCPauseMillis=200(设置最大GC停顿时间为200ms),平衡吞吐量和响应时间。线程和连接池的不合理配置会导致内存占用过高:
server.xml中配置<Connector>标签的maxThreads(最大线程数,默认200,根据服务器CPU核心数调整,如4核可设为200-400)、minSpareThreads(最小空闲线程数,默认10)、acceptCount(等待队列大小,默认100,队列满会拒绝请求)。maxConnections(最大连接数,根据数据库承受能力设置,如MySQL默认最大连接数151)、maxIdleTime(连接最大空闲时间,如30分钟)等参数,避免连接泄漏或过多闲置连接占用内存。Prometheus+Grafana、Zabbix)实时监控Tomcat的内存使用率、GC频率、线程数等指标,设置告警阈值(如堆内存使用率达80%时告警),及时发现并处理内存异常。