У меня есть программа, которая со временем постепенно использует все больше и больше памяти. Я использую 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
Хотя итоги здесь не складываются, в момент создания дампа кучи процесс использовал более 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 проверяет ссылки? Если да, то что еще я могу сделать, чтобы отследить мою «недостающую» память? Какие еще шаги я могу предпринять, чтобы отследить это?