当并非所有使用的堆都可以从线程访问时查找Java内存泄漏

Voi*_*ter 21 java debugging memory-leaks

我正在研究一个基于Java的大系统中潜在的内存泄漏(或至少是内存浪费).JVM的最大堆大小为5 GB,并且2-3GB堆使用量是应用程序的预期基线.(可能有更高的峰值)

在一个重载场景中,我正在调查堆被填满.使用"Eclipse MemoryAnalyzer Tool"分析堆转储显示(毫不奇怪)堆已完全用完.

MAT显示了两个潜在的泄漏候选者,两者大致保留了2.5GB:java.lang.Thread和系统中的域对象,该对象在系统中的事务处理期间广泛使用.但是,从Thread实例可以访问所有这些域对象(不足为奇).毕竟,这些线程正在处理事务.因此,归因于java.lang.Thread的2.5 GB几乎完全是由那些域对象引起的.这里不足为奇.

列出所有java.lang.Thread实例的对象树并总结所有线程的保留堆会导致2.5 GB的保留堆.

如果无法从java.lang.Thread实例访问堆,那么我应该在哪里寻找填充堆所需的其他2.5 GB? - 终结器队列中没有任何内容 - 没有大量无法访问的对象等待GC

我认为另一种提出这个问题的方法是:"如何找到所有从java.lang.Thread实例无法访问的对象?可能是一个OQL查询?",另一个问题是:"那里有什么样的对象无法从java.lang.Thread的实例到达终结器队列中的对象和待处理GC的未引用对象吗?"

dbw*_*dbw 4

我也在我们的网站上遇到了内存泄漏的问题,
使用yourkit java profiler它提供了大量的信息,并且凭借它的能力,您可以在所有内存都被利用的情况下获得更广泛的图像。
您可以找到一个很棒的教程“使用上述工具 查找 Java 内存泄漏” 。

你的问题,

“除了 Finalizer 队列中的对象和挂起 GC 的未引用对象之外,还有哪些类型的对象无法从 java.lang.Thread 实例访问?”

有四种对象,

  1. 强可达性,可以通过活动对象的引用直接到达的对象
  2. 弱/软可达,具有与之关联的弱/软引用的对象
  3. Pending Finalization,等待终结的对象,并且可以通过终结器队列访问其引用
  4. Unreachable 这些是从 GC root 无法访问但尚未收集的对象

除此之外,JVM 还使用本机内存,您可以在JVM 的 IBM 堆和本机内存使用上找到其信息,感谢您提供内存 ,根据 YourKit,JVM 内存结构具有非堆内存,其定义为

另外,JVM 还有堆以外的内存,称为非堆内存。它在 JVM 启动时创建,存储每个类的结构,例如运行时常量池、字段和方法数据、方法和构造函数的代码以及内部字符串。