2016-02-12 3 views
3

Предположим, что в одной руке у нас есть буфер с прямым байтом, созданный с помощью env->NewDirectByteBuffer(). В другой руке у нас есть аналогичный прямой буфер, но с ByteBuffer.allocateDirect(). Очевидно, что обе эти объекты должны управляться JVM таким же образом, включая управление встроенным буфером поддержки, который в первом случае был предоставлен пользователем, а во втором случае был выделен JVM из собственной кучи.Прямые буферы JNI. Кто отвечает за освобождение собственного буфера?

Конечно, JVM должен иметь свободный буфер поддержки во время GC'ing второго объекта (созданный с помощью ByteBuffer.allocateDirect()).

И мой вопрос: сможет ли JVM освободить буфер во время GC'ing первого объекта (созданный с помощью env->NewDirectByteBuffer())?

P.S. Я не нашел четкого ответа ни на JNI, ни на SO. Наиболее полезная информация была здесь http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html:

объектов Direct ByteBuffer очистить свои собственные буфера автоматически , но могут сделать это только как часть Java кучи GC - поэтому они не автоматически реагировать на давление на родную куче.

Итак, похоже, что JVM будет освобождать буферные буферы во время прохождения GC, но нет никаких упоминаний об deallocator. Это просто free() или что-то еще.

ответ

2

Когда вы вызываете JNI NewDirectByteBuffer(void* address, jlong capacity)DirectByteBuffer объект будет создан, используя следующий конструктор:

private DirectByteBuffer(long addr, int cap) { 
    super(-1, 0, cap, cap); 
    address = addr; 
    cleaner = null; 
    att = null; 
} 

Обратите внимание, что cleaner свойство является пустым.

При создании DirectByteBuffer через ByteBuffer.allocateDirect()cleaner свойства устанавливаются (см исходного кода DirectByteBuffer).

Теперь очиститель является объектом утилиты, метод clean запускается, когда буфер собран из мусора (подробнее см. Этот explanation).

Для буфера, построенного через ByteBuffer.allocateDirect(), очиститель освобождает прямую память.

Для построенного буфера JNI такая операция не выполняется. Вам нужно освободить эту память самостоятельно.

+0

Очистить. Похоже, что Android использует тот же подход. Android SDK содержит исчерпывающий комментарий: '/ ** * Представляет собой блок памяти, который у нас нет. (Мы не берем права собственности на соответствующую память * на прямые буферы, созданные функцией JNI NewDirectByteBuffer.) */' – Sergio