2016-03-18 3 views
4

Так как это из jvm heap & gc, когда он выпущен? Или он остается до завершения процесса?Java - Когда освобождается прямой буфер?

Я уже проверил:

Но все ответы размытость, никто не ответил на это явно, это там есть четкий ответ? По крайней мере, для Java 8 на 64-разрядный Linux.

+1

Когда сборщик 'ByteBuffer' собрал мусор, финализатор выполнит и освободит любое базовое распределение памяти. – Andreas

+0

Поскольку у вас нет гарантии, что он будет освобожден, я предлагаю вам позаботиться об этом самостоятельно, я разделил ['BufferUtils'] (https://github.com/jMonkeyEngine/jmonkeyengine/blob/ master/jme3-core/src/main/java/com/jme3/util/BufferUtils.java) из JM3 для моих проектов, например [здесь] (https://github.com/elect86/jogl-samples/blob/ master/jogl-samples/src/framework/BufferUtils.java), и до сих пор он работает безупречно – elect

+0

@elect Да, некоторые книги также говорят, что это для больших и длинных буферов, поэтому задержка выделения будет иметь меньшее влияние. Для небольшого и короткоживущего буфера рекомендуется использовать «прямой буфер», вместо этого использовать «косвенный буфер». –

ответ

13

DirectByteBuffer не использует старые Java-финализаторы. Вместо этого он использует внутренний sun.misc.Cleaner API. Он создает новый поток и сохраняет PhantomReference для каждого созданного DirectByteBuffer (за исключением дубликатов и фрагментов, относящихся к основному буферу). Когда DirectByteBuffer становится phantom-достижимым (то есть нет сильных, мягких или слабых ссылок на буфер байта) и сборщик мусора видит это, он добавляет этот буфер в ReferenceQueue, который обрабатывается потоком Cleaner. Таким образом, должны произойти три события:

  • DirectByteBuffer становится доступным для фантома.
  • Выполняется сбор мусора (в отдельной теме), DirectByteBuffer Объект Java собран, и запись добавляется к ReferenceQueue.
  • Cleaner thread достигает этой записи и запускает зарегистрированное очищающее действие (в данном случае это объект java.nio.DirectByteBuffer.Deallocator), это действие, наконец, освобождает встроенную память.

Таким образом, у вас нет гарантии, когда он будет освобожден. Если у вас достаточно памяти в куче Java, сборщик мусора может не активироваться в течение длительного времени. Кроме того, даже когда это доступно для фантома, для чистой записи может понадобиться некоторое время, чтобы достичь этой записи. Возможно, он занят обработкой предыдущих объектов, которые также использовали API Cleaner. Обратите внимание, однако, что частичная обработка выполняется в JDK: если вы создаете новый DirectByteBuffer и раньше выделяли слишком много прямой памяти, сборщик мусора может быть явно вызван для принудительного освобождения ранее заброшенных буферов. См. Bits.reserveMemory() (вызванный от DirectByteBuffer конструктор) для деталей.

Обратите внимание, что в Java-9 внутренний API Cleaner был исправлен и опубликован для общего использования: теперь это java.lang.ref.Cleaner. Читая JavaDoc, вы можете получить более подробную информацию о том, как это работает.

Смежные вопросы