Прямые буферы NIO используют неуправляемую память. Это означает, что они расположены в собственной куче, а не в куче Java. Как следствие, они освобождаются только тогда, когда JVM не хватает памяти в куче Java, а не в собственной куче. Другими словами, это неуправляемо = вам решать управлять ими. Принудительный сбор мусора не рекомендуется и большую часть времени не решает эту проблему.
Когда вы знаете, что прямой буфер NIO стал для вас бесполезным, вы должны освободить его собственную память, используя его sun.misc.Cleaner (StaxMan прав) и вызвать clean () (кроме Apache Harmony), вызвать free () (с Apache Harmony) или используйте лучший публичный API для этого (возможно, в Java> = 1.9, AutoCleaning, расширяющий AutoCloseable?).
Это не работа JOGL, вы можете использовать простой Java-код, чтобы сделать это самостоятельно. Мой пример под GPL v2, а этот пример под более разрешительной лицензией.
Редактировать .: Мой последний пример работает даже с Java 1.9 и поддерживает OpenJDK, Oracle Java, Sun Java, Apache Harmony, GNU Classpath и Android. Возможно, вам придется удалить некоторый синтаксический сахар, чтобы он работал с Java <1.7 (мульти-уловы, алмазы и дженерики). </p>
Ссылка: http://www.ibm.com/developerworks/library/j-nativememory-linux/
Объекты Direct ByteBuffer автоматически очищают свои собственные буферы
но может сделать это только как часть кучи Java GC - так они не делают
автоматически реагировать на давление на родную кучу. GC происходит только
когда куча Java становится настолько полной, она не может обслуживать выделение кучи
запрос или если приложение Java явно запрашивает его (не
рекомендуется, поскольку это вызывает проблемы с производительностью).
Ссылка: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct
Содержимое прямых буферов может находиться вне обычной кучи для сбора мусора
Это решение (в этом JEP , все еще черновик, вероятно, недоступен в Java 1.9) очень многообещающе, нам не нужно будет использовать непубличные API.
public long memory(long index) {
// The scope where the memory region is available
// Implements AutoClosable but `close` can be called manually as well
try (Scope scope = new NativeScope()) {
// Allocate the actual memory area, in this case in the style of a "long-array"
Pointer<Long> ptr = scope.allocate(
NativeLibrary.createLayout(long.class), numElements);
// Get the reference to a certain element
Reference<Long> ref = ptr.offset(index).deref();
// Set a value to this element through the reference
ref.set(Long.MAX_VALUE);
// Read the value of an element
return ref.get();
}
}
NB: sun.misc.Cleaner был перемещен в jdk.internal.ref.Cleaner в Java 1.9 в модуле "java.base", но последний реализует Java. lang.Runnable (спасибо Алану Бейтману за напоминание об этой разнице). Затем вам просто нужно привести очиститель к Runnable и вызвать метод run()
(не вызывайте его по отражению, чтобы избежать получения исключения java.lang.IllegalAccessException). Это работает, я только что протестировал (6 августа 2016 г.) с Java 1.9 Early Access build 129.
Однако jdk.internal.ref.Cleaner может быть перемещен в java.ref.Cleaner $. Очистится позже.
В Lucene есть хороший пример
с более разрешительной лицензией. *1048*