Лучшие способы идентифицировать объекты, не собирающие мусор? - PullRequest
8 голосов
/ 21 декабря 2010

В двух словах

У меня есть программа, которая постепенно использует все больше и больше памяти. Я использую jmap и jhat, чтобы попытаться диагностировать его, но я все еще не совсем там.

Фон

Программа - это долго работающий сервер, поддерживаемый хранилищем данных hbase, обеспечивающий экономный сервис для множества других вещей. Однако после нескольких дней работы он в конечном итоге достигнет предела выделенной кучи и будет перемещаться туда-сюда, почти все время тратится на сборку мусора. Казалось бы, ссылки хранятся где-то на большом количестве данных

Что я сделал до сих пор

После того, как я немного поигрался с jstat и jconsole, я в итоге взял heapdumps с 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

Хотя итоговые значения здесь не суммируются, в момент, когда был взят дамп кучи, процесс использовал более 1 ГБ памяти.

Непосредственный очевидный виновник, похоже, повсюду оставляет записи HBase Result и 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

Требуется помощь:

Кажется, нет никаких ссылок на этот последний объект HBaseCLient $ Call (или любой другой подобный ему, каждый из которых содержит около тысячи значений ключа со всеми своими внутренними данными). Разве это не должно быть GCed? Я просто неправильно понимаю, как работает gc или в какой степени jhat будет проверять ссылки? Если так, что еще я могу сделать, чтобы отследить мою «недостающую» память? Какие еще шаги я могу предпринять, чтобы отследить это?

Ответы [ 3 ]

3 голосов
/ 21 декабря 2010

Проверьте эту статью о мониторинге памяти Java Ссылка

Это может помочь вам решить вашу проблему http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

1 голос
/ 21 декабря 2010

Вы можете попробовать JProfiler 10 дней бесплатно.С JProfiler вы решите эту проблему за несколько минут.

0 голосов
/ 21 декабря 2010

Я рекомендую сначала попробовать JVisualVM, который распространяется с последней версией JDK.

Кроме того, если вы можете оправдать стоимость, я считаю JProfiler отличным инструментом на протяжении многих лет.

...