【问题标题】:Java memory leak - jmap doesn't show the classes but jstat doesJava 内存泄漏 - jmap 不显示类,但 jstat 显示
【发布时间】:2017-01-29 16:16:45
【问题描述】:

我解决了一个奇怪的内存泄漏问题。它特定于 Java8,不会发生在 7u79 上。

我无权访问 Java 代码。 我确切地知道哪个用户操作导致了泄漏,我知道泄漏是关于类(而不是堆),并且通过 +TraceClassLoading +TraceClassUnloading 很容易发现有问题的类:

[Loaded com.mastercard.mcwallet.sdk.xml.allservices.ShoppingCartRequest$JaxbAccessorF_oAuthToken from __JVM_DefineClass__]
[Loaded com.mastercard.mcwallet.sdk.... thousand similar classes per one user action... ]

这些类似乎将类计数器输出增加了jstat -class

Loaded  Bytes  Unloaded  Bytes     Time
 14045 26138.8        0     0.0     110.00   << buggy user action
 14675 26754.6        0     0.0     110.05
 15300 27364.9        0     0.0     110.10
 15304 27370.9        0     0.0     110.11
 15304 27370.9        0     0.0     110.11
 15304 27370.9        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11   << buggy user action
 15930 27982.2        0     0.0     110.18
 16553 28589.3        0     0.0     110.23
 16553 28589.3        0     0.0     110.23

问题是这些类永远不会从元空间中进行垃圾收集,永远不会从 [Unloaded] 中收集,并且它们不会显示在 jmap -clstats 中。该命令报告的类数量较少,数量没有增加,没有可疑的类加载器:

class_loader    classes bytes   parent_loader   alive?  type

<bootstrap>     2574    4493256   null          live    <internal>
0x0000000087d016d0      1       1471    0x000000008237f088      dead    sun/reflect/DelegatingClassLoader@0x00007ff4135d02d0
... some lines omitted ...
0x000000008237f088      6505    12228227        0x0000000080383938      dead    org/apache/catalina/loader/WebappClassLoader@0x00007ff411546ad0
... some lines omitted ...
total = 600     14002   25351427            N/A         alive=1, dead=599           N/A

这是否敲响了警钟或带来了我可以传递给程序员的任何提示?他们说他们无法找到泄漏点。我可以通过摆弄 JVM 选项来阻止这种泄漏吗?

【问题讨论】:

  • 只有MetaSpace 的问题? heap 呢?还能提供Java进程内存使用统计吗?
  • 只有元空间,堆是稳定的,不是满的。究竟是什么统计数据?
  • 我的意思是 Java 进程内存使用增长的速度有多快?
  • 每个“错误用户操作”从操作系统分配大约 2 MB(pmap 工具甚至显示一个单独的 2 MB 段)。
  • 你是否尝试过使用不同的 GC 算法,例如 G1 -XX:+UseG1GC?或者您可以尝试将-XX:MaxMetaspaceSize=&lt;NNN&gt; 设置为预期定义Metaspace 的大小。

标签: java memory-leaks java-8 jmap


【解决方案1】:

如果错误的类无法卸载,那么它必须缓存在应用程序的某个位置,据我了解,您的目标是找到它的位置并为开发人员提供此信息。

您可以尝试使用 Eclipse 内存分析器 (MAT) 来检查您的堆转储,它可以显示问题区域、类和与错误类有链接的实例。

【讨论】:

    【解决方案2】:

    我认为 JaxB 正在将类加载到您的内存中,而这些类并未被垃圾收集。如果未卸载类,元空间不会清空。

    检查JaxB memory issue for Java 8。我认为您可以通过交换依赖项 api 版本或切换额外参数来摆脱此异常:

    -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      • 2014-02-18
      • 2012-06-20
      • 2011-10-10
      • 1970-01-01
      • 2019-07-17
      • 2021-12-25
      相关资源
      最近更新 更多