Java 内存泄漏 - jmap 不显示 类 但 jstat 显示

Java memory leak - jmap doesn't show the classes but jstat does

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

我无法访问 Java 代码。 我确切地知道是哪个用户操作导致了泄漏,我知道泄漏是关于 classes(不是堆)的,并且使用 +TraceClassLoading +TraceClassUnloading:[=18 很容易发现有问题的 classes =]

[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... ]

这些 classes 似乎增加了 class 计数器输出 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

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

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 选项来阻止这种泄漏吗?

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

您可以尝试使用 Eclipse Memory Analyzer (MAT) 检查您的堆转储,它可以显示问题区域,类 和链接到错误的实例 类.

我推测 JaxB 正在将 类 加载到您的内存中,而这些内存并未被垃圾回收。如果 类 没有被卸载,Metaspace 将不会被清空。

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

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