Утечка памяти Java-найти все объекты класса X, на которые не ссылается класс Y


У меня есть утечка памяти в Java, в которой у меня есть 9600 ImapClients в моем дампе кучи и только 7800 MonitoringTask s. это проблема, так как каждый ImapClient должен принадлежать MonitoringTask, поэтому эти дополнительные 1800 ImapClients просачиваются.

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

Определить наличие утечки сложно, поэтому вот моя полная ситуация:

  • этот процесс был изрыгая Омес неделю назад. Я думал, что починил его, и я пытаюсь проверить, сработал ли мой фиксированный, не дожидаясь еще целую неделю, чтобы увидеть, извергает ли он снова Оомы.
  • эта задача создает 7000-9000 ImapClientС на старте после чего при нормальной работе подключается и отключается очень немногие из них.
  • я проверил другой процесс, работающий с более старым кодом pre-OOME, и он показал цифры 9000/9100 вместо 7800/9600. Я не знаю, почему старый код будет отличаться от нового кода, но это свидетельство утечки.
Суть этого вопроса в том, чтобы я мог определить, есть ли утечка. Существует бизнес-правило, что каждый ImapClient должен быть рефери MonitoringTask. Если этот запрос, о котором я спрашиваю, окажется пустым, утечки не будет. Если он приходит с объектами, вместе с этим бизнес-правилом это не только свидетельство утечки, но и убедительное доказательство ее наличия.
3 2

3 ответа:

Ваши ожидания неверны, нет никаких фактических доказательств каких-либо утечек, происходящих

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

Только потому, что что-то является кандидатом на сбор мусора, не делает этого. значит, его когда-нибудь действительно соберут, и там это не способ принудительная сборка мусора либо.

Я нигде не вижу упоминания о OutOfMemoryError.

То, что вас беспокоит, вы не можете контролировать, во всяком случае напрямую

Вы должны сосредоточиться на том, что находится под вашим контролем, то есть убедиться, что вы не держите ссылки дольше, чем вам нужно, и что вы не дублируете вещи без необходимости. Процедуры сборки мусора в Java сильно оптимизированы, и если вы узнаете, как их алгоритмы работают, вы можете убедиться, что ваша программа ведет себя оптимальным образом для работы этих алгоритмов.

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

То, что считаетсяутечкой памяти в других языках, - это не то же самое/первопричина, что и в Java с ее системой сбора мусора.

Скорее всего, в Java память не потребляется одним единственным uber-объектом, который протекает ( висячая ссылка в другая среда ).

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

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

Сборщик мусора действительно хорош сейчас, но это не магия, если вы делаете дегенеративные вещи, это приведет к тому, что он не будет работать оптимально. В интернете есть много документации о настройках сборщика мусора для всех версий JVMs.

Эти объекты без ссылок могут просто не достичь времени, которое сборщик мусора считает необходимым для их удаления из памяти, или могут быть ссылки на них, удерживаемые каким-либо другим например, объект (List), который вы не осознаете, все еще указывает на этот объект. Это то, что чаще всего называют утечкой в Java, которая является ссылочной утечкой более конкретно.

Я не вижу никаких упоминаний об этом.OutOfMemoryError

У вас, вероятно, нет проблем в коде, система сбора мусора просто не может быть поставлена под достаточное давление, чтобы запустить и освободить объекты, которые вы считаете, что она должна очищать. Что вы подумайте, что - Это проблема, вероятно, нет, если только ваша программа не падает с OutOfMemoryError. Это не C, C++, Objective-C или любой другой язык ручного управления памятью / среда выполнения. Вы не можете решить, что находится в памяти или нет на уровне детализации, который вы ожидаете, что вы должны быть в состоянии.

Проверьте свой код на наличие финализаторов, особенно на все, что связано с IMapclient.

Возможно, что ваши задачи мониторинга легко собираются, в то время как ваши IMapclient завершены, и поэтому остаются в куче (хотя и мертвы), пока не запустится поток финализатора.

Очевидный ответ-добавить WeakHashMap<X, Object>Y) в свой код-один отслеживает все экземпляры X, а другой отслеживает все экземпляры Y (сделайте их статическими членами класса и вставьте каждый объект в карту в конструкторе с нулевым "значением"). Затем вы можете в любое время перебирать эти карты, чтобы найти все живые экземпляры X и Y и посмотреть, на какие Xs не ссылается Ys. Возможно, вы захотите сначала запустить полный GC, чтобы игнорировать объекты, которые мертвы и еще не собраны.