You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从JDK 8迁移至JDK 17后应用内存占用过高问题求助

JDK 17+Tomcat 9迁移后非堆内存暴涨排查方向
  • 排查Metaspace占用变化
    JDK 8的PermGen被替换为Metaspace,默认无固定上限(受系统内存限制)。迁移后可能因为Tomcat 9自身类加载量增加、JDK 17自带类更多,或者依赖包在JDK 17下触发类重复加载,导致Metaspace占用飙升。执行jcmd <pid> VM.metaspace查看当前Metaspace的已用、提交和最大值,对比JDK 8时期的PermGen数据。

  • 检查Direct ByteBuffer内存
    Tomcat 9默认使用NIO连接器,JDK 17对NIO的Direct Buffer回收机制或默认阈值可能有调整。如果应用大量使用NIO或依赖框架(如Netty),可能存在Direct Buffer未及时回收的情况。用jcmd <pid> VM.native_memory detail查看Direct Memory的占用明细,或在JFR中筛选Direct Buffer Allocation事件,定位大内存分配点。

  • 分析Tomcat自身配置与组件
    Tomcat 9的默认配置(如线程池maxThreads、连接器缓冲区bufferSize)和新增特性(如HTTP/2、WebSocket默认支持)可能占用更多内存。检查server.xml中的Connector配置,确认是否开启了不必要的组件(如RewriteValve、RemoteIpValve),对比Tomcat 7时期的配置差异。

  • 核对JVM默认参数变更
    JDK 17的部分非堆区域默认值与JDK 8不同:比如CompressedClassSpaceSize默认从1G调整为2G,CodeCache因分层编译优化可能占用更多内存。执行jcmd <pid> VM.codecache查看CodeCache的使用情况,对比JDK 8时期的参数配置,必要时手动指定-XX:CompressedClassSpaceSize、-XX:ReservedCodeCacheSize限制非堆内存。

  • 排查类加载器泄漏
    Tomcat 9的WebappClassLoader实现有优化,但部分旧依赖可能存在类加载器泄漏问题(如静态引用持有类加载器)。用jmap -histo:live <pid>生成两次间隔一段时间的类直方图,对比类数量增长情况;或在JFR中监控Class Load和Class Unload事件,确认是否存在类无法卸载的情况。

  • 验证第三方依赖兼容性
    部分依赖库在JDK 17下可能因反射、Unsafe API或JNI调用的行为变化导致内存泄漏。检查依赖包版本是否适配JDK 17,尤其是使用JNI的原生库;用JFR监控JNI Global Reference事件,查看是否有未释放的全局引用。

  • 启用Native Memory Tracking(NMT)对比
    启动JVM时添加-XX:NativeMemoryTracking=detail,先执行jcmd <pid> VM.native_memory baseline建立基准,运行一段时间后执行jcmd <pid> VM.native_memory diff,通过对比数据定位内存增长的具体区域(如类加载、线程栈、JNI等)。

内容的提问来源于stack exchange,提问作者Rajat Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:46:18