Java 识别未被垃圾收集的对象的更好方法? 简而言之

Java 识别未被垃圾收集的对象的更好方法? 简而言之,java,debugging,garbage-collection,jvm,jhat,Java,Debugging,Garbage Collection,Jvm,Jhat,我有一个程序,随着时间的推移逐渐使用越来越多的内存。我正在使用jmap和jhat来尝试和诊断它,但仍然不太清楚 背景 该程序是一个长期运行的服务器,由一个hbase数据存储支持,为其他一些东西提供一个节俭服务。然而,在运行几天后,它最终将达到分配的堆限制,并且几乎所有的时间都花在垃圾收集上。似乎参考文献在某处保存了大量数据 到目前为止我做了什么 在摆弄了jstat和jconsole之后,我最终用运行进程的jmap进行了堆转储,并通过jhat运行它,简单的数字加起来与内存利用率相差甚远 jmap-

我有一个程序,随着时间的推移逐渐使用越来越多的内存。我正在使用jmap和jhat来尝试和诊断它,但仍然不太清楚

背景 该程序是一个长期运行的服务器,由一个hbase数据存储支持,为其他一些东西提供一个节俭服务。然而,在运行几天后,它最终将达到分配的堆限制,并且几乎所有的时间都花在垃圾收集上。似乎参考文献在某处保存了大量数据

到目前为止我做了什么 在摆弄了jstat和jconsole之后,我最终用运行进程的jmap进行了堆转储,并通过jhat运行它,简单的数字加起来与内存利用率相差甚远

jmap-F-dump:live,format=b,file=heap.dump 12765

jmap-F-dump:format=b,file=heap.all 12765

柱状图顶部的一些东西

Class   Instance Count  Total Size
class [B     7493    228042570
class java.util.HashMap$Entry    2833152     79328256
class [Ljava.util.HashMap$Entry;     541     33647856
class [Ljava.lang.Object;    303698  29106440
class java.lang.Long     2851889     22815112
class org.apache.hadoop.hbase.KeyValue   303593  13358092
class org.apache.hadoop.hbase.client.Result  303592  9714944
class [I     14074   9146580
class java.util.LinkedList$Entry     303841  7292184
class [Lorg.apache.hadoop.hbase.KeyValue;    303592  7286208
class org.apache.hadoop.hbase.io.ImmutableBytesWritable  305097  4881552
class java.util.ArrayList    302633  4842128
class [Lorg.apache.hadoop.hbase.client.Result;   297     2433488
class [C     5391    320190
虽然这里的总数加起来不算在内,但在进行堆转储时,进程使用了超过1gb的内存

最直接的罪魁祸首似乎是我把HBase结果和KeyValue条目放得到处都是。我试图追查参考资料,最终找到了

Object at 0x2aab091e46d0

instance of org.apache.hadoop.hbase.ipc.HBaseClient$Call@0x2aab091e46d0 (53 bytes)

Class:

class org.apache.hadoop.hbase.ipc.HBaseClient$Call
Instance data members:

done (Z) : true
error (L) : <null>
id (I) : 57316
param (L) : org.apache.hadoop.hbase.ipc.HBaseRPC$Invocation@0x2aab091e4678 (48 bytes) 
this$0 (L) : org.apache.hadoop.hbase.ipc.HBaseClient@0x2aaabfb78f30 (86 bytes) 
value (L) : org.apache.hadoop.hbase.io.HbaseObjectWritable@0x2aab092e31c0 (40 bytes) 
References to this object:

Other Queries

Reference Chains from Rootset
Exclude weak refs
Include weak refs
Objects reachable from here
0x2aab091e46d0处的
对象
org.apache.hadoop.hbase.ipc.HBaseClient的实例$Call@0x2aab091e46d0(53字节)
类别:
类org.apache.hadoop.hbase.ipc.HBaseClient$调用
实例数据成员:
完成(Z):正确
错误(L):
id(I):57316
参数(L):org.apache.hadoop.hbase.ipc.HBaseRPC$Invocation@0x2aab091e4678(48字节)
这个$0(L):org.apache.hadoop.hbase.ipc。HBaseClient@0x2aaabfb78f30(86字节)
值(L):org.apache.hadoop.hbase.io。HbaseObjectWritable@0x2aab092e31c0(40字节)
对该对象的引用:
其他查询
根集的引用链
排除弱引用
包括弱引用
从这里可以到达的对象
所需帮助:
似乎没有引用这个最终的HBaseCLient$Call对象(或任何其他类似对象,每个对象都包含一千个左右的键值及其所有内部数据)。是不是应该考GCD?我是否只是误解了gc的工作方式或jhat将在多大程度上验证参考资料?如果是这样,我还能做些什么来追踪我“丢失”的记忆?我还可以采取哪些其他步骤来追踪这一点?

我建议首先尝试使用最新JDK发行的JVisualVM


另外,如果您能证明成本的合理性,那么多年来,我发现JProfiler是一个优秀的工具。

查看这篇Java内存监控文章

这可能会帮助你解决你的问题
您可以免费试用JProfiler 10天。使用JProfiler,您将在几分钟内解决此问题。

您试用过JProfiler吗?非常好。比jhat好用多了。完全披露:我在JProfiler的制造商中没有任何股份:)我没有尝试过JProfiler,尽管我也在使用eclipse内存分析透视图。我会试着戳一下,但我已经说到了一点,我非常确定数据实际上没有泄漏,只是默认情况下gc设置可能过于宽松,因为我的幸存者空间每个都将提交100mb,但很少有太多的使用量(在大的计算过程中,它会出现峰值)是的,我是在自己想办法解决这个问题时偶然发现那篇文章的。这是非常有益的