Java:非堆内存分析

我们遇到的问题是我们的非堆内存一直在增长。 所以我们必须每隔3天重新启动我们的jee(java8) – webapp(正如你在这里的截图中看到的那样: 来自非堆和堆内存的截图 )

我已经试图找出填满非堆的东西了。 但我找不到任何工具来创建非堆转储。 你有什么想法我可以调查一下,找出哪些元素越来越多?

Java的版本

java version "1.8.0_102" Java(TM) SE Runtime Environment (build 1.8.0_102-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode) 

Tomcat的版本

 Apache Tomcat Version 7.0.59 

MemoryPoolMXBean提供的非堆内存使用情况会计算以下内存池:

  • 元空间
  • 压缩类空间
  • 代码缓存

换句话说,标准的非堆内存统计信息包括已编译方法和已加载类占用的空间。 最有可能的是,增加的非堆内存使用量表明类加载器泄漏。

使用

  • jmap -clstats PID转储类加载器统计信息;
  • jcmd PID GC.class_stats用于打印有关每个已加载类的内存使用情况的详细信息。 后者需要-XX:+UnlockDiagnosticVMOptions

使用Java 8,类元数据现在位于名为Metaspace的非堆内存部分中(而不再是PermGen中)。 如果您的非堆内存主要由Metaspace使用 ,您可以使用jstat来计算它。

它不是分析非堆内存的通用工具。 但它可能仍然有助于你的情况。

正如@apangin指出的那样,随着时间的推移你似乎正在使用更多的Metaspace。 这通常意味着您要加载更多类。 我将记录正在加载的类和正在编译的方法,并尝试限制在生产中连续完成的程度。 您可能有一个库,它连续生成代码但不清理它。 在这里查看正在创建的类可以给你一个关于哪一个类的提示。


对于本机非堆内存。

您可以使用/proc/{pid}/maps查看Linux上的内存映射。这将告诉您正在使用多少虚拟内存。

你需要确定这是否是由于

  • 越来越多的线程或套接字
  • 直接使用ByteBuffers。
  • 使用本机/直接内存的第三方库。

从查看图表可以减少堆积并增加最大直接内存并将重启时间延长到一周或更长时间,但更好的解决方案是解决问题。