首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >识别未被垃圾回收的对象的更好方法?

识别未被垃圾回收的对象的更好方法?
EN

Stack Overflow用户
提问于 2010-12-21 10:39:28
回答 3查看 1.5K关注 0票数 8

简而言之

我有一个程序,随着时间的推移,它会逐渐使用越来越多的内存。我正在使用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

直方图顶部的一些东西

代码语言:javascript
复制
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

虽然这里的总数没有加起来,但在获取堆转储时,该进程使用了超过1 1gb的内存。

直接的罪魁祸首似乎是我把HBase Result和KeyValue条目弄得到处都是。试图追踪参考文献,我最终找到了

代码语言:javascript
复制
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

需要帮助:

似乎没有引用这个最终的HBaseCLient$Call对象(或任何其他类似的对象,每个对象都包含一千个左右的键值及其所有内部数据)。它不应该得到GCed吗?我只是误解了gc是如何工作的,还是jhat将在多大程度上验证引用?如果是这样,我还能做些什么来找回我“丢失”的记忆呢?我还可以采取什么其他步骤来追踪这个问题?

EN

回答 3

Stack Overflow用户

发布于 2010-12-21 10:54:55

查看这篇Java Memory Monitoring文章Link

这可能会帮助你克服你的问题http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

票数 3
EN

Stack Overflow用户

发布于 2010-12-21 16:29:24

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

票数 1
EN

Stack Overflow用户

发布于 2010-12-21 10:47:14

我建议先试用JVisualVM,它随最新的JDK一起发布。

此外,如果你能证明成本是合理的,那么多年来,我发现JProfiler是一个很好的工具。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4495849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档