Что удерживает мой ByteBuffer от освобождения? - PullRequest
3 голосов
/ 31 октября 2011

Я выделяю много байтовых буферов. После того, как я закончил с ними, я установил все ссылки на ноль. Это якобы «правильный» способ освобождения байтовых буферов? Разыменовывать это и позволить GC очистить это? Я также вызываю System.gc (), чтобы попытаться помочь ему в этом.

В любом случае, я создаю кучу буферов, уважаю их; но через некоторое время я получаю всевозможные ошибки памяти: java.lang.OutOfMemoryError: прямая буферная память

Я могу увеличить MaxDirectMemorySize, но это только задерживает вышеуказанную ошибку.

Я на 99% уверен, что у меня нет ссылок на старые ByteBuffers. Есть ли способ проверить это, чтобы увидеть, что, черт возьми, еще выделил ByteBuffer?

Ответы [ 4 ]

1 голос
/ 31 октября 2011

Установка ссылок на null - это правильный способ разрешить сборщику мусора завершить работу с этим объектом. Там должно быть еще какая-то висящая ссылка. Лучший инструмент для обнаружения утечек памяти - YourKit . Бесплатная альтернатива, которая также очень хороша - Visual VM из JDK .

Помните, что операция slice () создает новый байтовый буфер, который ссылается на первый.

1 голос
/ 31 октября 2011

Вы можете использовать такой инструмент, как MAT, который бесплатен в Eclipse, чтобы увидеть, что хранит ваш байтовый буфер, позволив ему выполнить некоторый анализ heapdump.

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

Также Systen.gc () не гарантирует, что финализаторы будут выполнены, вам нужно выполнить System.runFinalization (), чтобы увеличить вероятность.

0 голосов
/ 25 июня 2015

Direct java.nio.ByteBuffer (по определению) хранится вне пространства кучи Java. Он не освобождается, пока GC не работает в куче и не освобождает его. Но вы можете представить себе ситуацию, когда использование кучи низкое, поэтому для него не требуется сборщик мусора, но не куча памяти выделяется и выходит за пределы.

На основании очень интересного прочтения: http://www.ibm.com/developerworks/library/j-nativememory-linux/

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

0 голосов
/ 31 октября 2011

Это проблема со старыми версиями Java. Последняя версия Java 6 вызовет System.gc (), прежде чем выдать ошибку OutOfMemoryError. Если вы не хотите запускать GC, вы можете освободить прямую память вручную на Oracle / Sun JVM с помощью

((DirectBuffer) buffer).cleaner().clean();

Однако лучше перерабатывать прямые буферы самостоятельно, поэтому делать это не так критично. (Создание прямых ByteBuffers относительно дорого)

...