Передача исходной памяти прямого буфера в Java для JOGL

Я использую прямые буферы (java.nio) для хранения информации о вершинах для JOGL. Эти буферы являются большими, и они заменяются несколько раз в течение срока службы. Память не освобождается во времени, и после нескольких замен я теряю память.

Кажется, что нет хорошего способа освободить использование classов буфера java.nio. Мой вопрос таков:

Есть ли какой-нибудь метод в JOGL для удаления прямых буферов? Я смотрю glDeleteBuffer (), но похоже, что это удаляет только буфер из памяти видеокарты.

благодаря

Прямые буферы NIO используют неуправляемую память. Это означает, что они выделяются на нативной куче, а не на куче Java. Как следствие, они освобождаются только тогда, когда у JVM заканчивается память на куче Java, а не на нативной куче. Другими словами, он неуправляемый = вам решать, как управлять ими. Принуждение сбора мусора не рекомендуется и не будет решать эту проблему большую часть времени.

Когда вы знаете, что прямой буфер NIO стал для вас бесполезным, вы должны освободить его собственную память, используя его sun.misc.Cleaner (StaxMan прав) и вызовите clean () (за исключением Apache Harmony), позвоните бесплатно () (с Apache Harmony) или использовать более открытый публичный API для этого (возможно, в Java> = 1.9, AutoCleaning, который расширяет AutoCloseable?).

Это не работа JOGL, вы можете использовать простой Java-код, чтобы сделать это самостоятельно. Мой пример находится под GPL v2, и этот пример находится под более разрешительной лицензией.

Edit .: Мой последний пример работает даже с Java 1.9 и поддерживает OpenJDK, Oracle Java, Sun Java, Apache Harmony, GNU Classpath и Android. Возможно, вам придется удалить синтаксический сахар, чтобы он работал с Java <1.7 (многократные уловы, бриллианты и дженерики).

Ссылка: http://www.ibm.com/developerworks/library/j-nativememory-linux/

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

Ссылка: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct

Содержимое прямых буферов может находиться вне обычной мусорной кучи

Это решение (в этом JEP , все еще черновик, возможно, неansible в 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 ptr = scope.allocate( NativeLibrary.createLayout(long.class), numElements); // Get the reference to a certain element Reference 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 (спасибо Алану Бейтмену за то, что он напомнил мне эту разницу). Затем вам нужно просто run() очиститель в Runnable и вызвать метод run() (не называть его reflectionм, чтобы избежать получения java.lang.IllegalAccessException). Он работает, я только что проверил (6 августа 2016 года) с Java 1.9 Early Access build 129.

Однако jdk.internal.ref.Cleaner может быть перемещен в java.ref.Cleaner $ Cleanable позже.

В Lucene есть хороший пример с более разрешительной лицензией.

Прямые буферы сложны и не имеют обычных гарантий сбора мусора – см. Более подробную информацию: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct

Если у вас возникли проблемы, я бы предложил выделить один раз и повторно использовать буфер, а не выделять и освобождать повторно.

Освобождение прямого буфера – это работа, выполняемая сборщиком мусора через некоторое время после того, как объект ByteBuffer отмечен.

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

Способ, по которому делается освобождение, ужасен – мягкая ссылка в основном вставляется в объект Cleaner, который затем выполняет освобождение при использовании ByteBuffer для сбора мусора. Но на самом деле это не гарантируется своевременно.

Вместо того, чтобы злоупотреблять reflectionм непубличной apis, вы можете сделать это тривиально, полностью в поддерживаемых публичных.

Напишите некоторый JNI, который обертывает malloc с помощью NewDirectByteBuffer (не забудьте установить порядок) и аналогичную функцию, чтобы освободить его.

  • Как я могу получить размер блока памяти, выделенного с помощью malloc ()?
  • Почему у меня возникают разные результаты, когда я разыгрываю указатель после его освобождения?
  • Начальная емкость вектора в C ++
  • Как получить текущее использование памяти в Android?
  • Android Studio - Как увеличить размер выделенной кучи
  • Сведения о переполнении памяти Linux
  • Самый эффективный способ добавления массивов в C #?
  • bds 2006 C конфликты с скрытым диспетчером памяти (class new / delete vs. AnsiString)
  • Какова стоимость использования автореферата в cocoa?
  • Установка объектов на Null / Nothing после использования в .NET.
  • Разделение памяти Android
  • Давайте будем гением компьютера.