【问题标题】:Java: non-heap-memory analyzesJava:非堆内存分析
【发布时间】:2017-01-12 18:10:28
【问题描述】:

我们的问题是我们的非堆内存一直在增长。所以我们必须每 3 天重新启动一次 jee (java8) - webapp(如您在此处的屏幕截图中所见:screenshot from non-heap- and heap-memory

我已经尝试找出填充非堆的内容。但我找不到任何工具来创建非堆转储。你知道我该如何调查以找出哪些元素在增长?

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

【问题讨论】:

  • 在下面的评论中你说它是一个嵌入式 tomcat。您可以在帖子中添加 JVM 版本和用于启动它的参数吗?
  • tomcat的版本也很重要
  • 谢谢@Stefan,如果你也有嵌入式tomcat的版本...
  • 自 Tomcat 7.0.59 版以来,一些内存泄漏错误已得到解决。可以升级吗?如果可行,另一种方法是将 jvm 降级到 1.7,验证是否存在 perm 空间 oom,以防万一使用非常成熟的工具(eclipse MAT,jmc,...)进行分析

标签: java memory-leaks jvm


【解决方案1】:

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

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

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

使用

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

【讨论】:

    【解决方案2】:

    正如@apangin 指出的那样,随着时间的推移,您似乎正在使用更多的元空间。这通常意味着您正在加载更多类。我会记录正在加载的类和正在编译的方法,并尝试限制在生产中连续进行的工作量。您可能有一个库,它连续生成代码但没有清理它。在这里查看正在创建的类可以提示您是哪个类。


    对于本机非堆内存。

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

    你需要确定这是否是由于

    • 增加线程或套接字的数量
    • 正在使用直接 ByteBuffers。
    • 使用本机/直接内存的第三方库。

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

    【讨论】:

    • 看起来 OP 的图表显示了MemoryPoolMXBean 提供的内存使用情况。标准非堆统计中不包含线程、套接字、直接字节缓冲区或第三方库内存。非堆池只是代码缓存、元空间和压缩类空间。就是这样。
    • 这是一个有趣的观察。然后它会指向类加载问题(例如部署新的 .war 或 .ear 文件,但旧版本未正确发布,或过多的动态字节码生成和加载,或两者兼而有之)。
    • 我们使用嵌入式 tomcat 运行 j2ee-web-app,所以没有 .war- 或 .ear-file-deployment
    【解决方案3】:

    在 Java 8 中,类元数据现在位于称为 Metaspace 的非堆内存部分中(不再位于 PermGen 中)。如果你的非堆内存主要被元空间消耗,你可以用jstat来解决。

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

    【讨论】:

      猜你喜欢
      • 2021-09-26
      • 2012-07-23
      • 2011-02-28
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      相关资源
      最近更新 更多