gpt4 book ai didi

java - 在 Java 中为 JOGL 释放直接缓冲区 native 内存

转载 作者:搜寻专家 更新时间:2023-10-30 19:56:58 24 4
gpt4 key购买 nike

我正在使用直接缓冲区 (java.nio) 来存储 JOGL 的顶点信息。这些缓冲区很大,在应用程序生命周期中会被更换多次。内存没有及时释放,更换几次后内存不足。

使用 java.nio 的缓冲类似乎没有很好的释放方法。我的问题是:

JOGL 中有删除直接缓冲区的方法吗?我正在研究 glDeleteBuffer(),但似乎这只会从视频卡内存中删除缓冲区。

谢谢

最佳答案

直接 NIO 缓冲区使用非托管内存。这意味着它们是在 native 堆上分配的,而不是在 Java 堆上。因此,只有当 JVM 用完 Java 堆上的内存时才会释放它们,而不是在 native 堆上。换句话说,它是不受管理的 = 由您来管理它们。强制垃圾收集是不鼓励的,并且在大多数情况下不会解决这个问题。

当你知道一个直接的 NIO 缓冲区已经对你无用时,你必须使用它的 sun.misc.Cleaner 释放它的 native 内存(StaxMan 是对的)并调用 clean()(Apache Harmony 除外),调用free()(使用 Apache Harmony)或使用更好的公共(public) API 来执行此操作(也许在 Java > 12 中,AutoCleaning 扩展了 AutoCloseable?)。

这不是 JOGL 的工作,您可以使用纯 Java 代码自己完成。 My example在 GPL v2 和 this example 下处于更宽松的许可之下。

编辑:My latest example甚至可以使用 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/

Direct ByteBuffer objects clean up their native buffers automaticallybut can only do so as part of Java heap GC — so they do notautomatically respond to pressure on the native heap. GC occurs onlywhen the Java heap becomes so full it can't service a heap-allocationrequest or if the Java application explicitly requests it (notrecommended because it causes performance problems).

引用:http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct

The contents of direct buffers may reside outside of the normal garbage-collected heap

This solution集成在 Java 14 中:

try (MemorySegment segment = MemorySegment.allocateNative(100)) {
...
}

您可以通过调用 MemorySegment.ofByteBuffer(ByteBuffer) 将字节缓冲区包装到内存段中, 在 Java 16 中获取它的内存地址并释放它(这是一个受限的方法):

CLinker.getInstance().freeMemoryRestricted(MemorySegment.ofByteBuffer(myByteBuffer).address());

请注意,在许多重要的情况下,您仍然需要使用反射来找到可以释放的缓冲区,通常是当您的直接 NIO 缓冲区不是 ByteBuffer 时。

注意:sun.misc.Cleaner 已移入 jdk.internal.ref.Cleaner在 Java 1.9 中的模块“java.base”中,后者实现了 java.lang.Runnable(感谢 Alan Bateman 提醒我这个区别)但时间很短但it's no longer the case .你必须调用 sun.misc.Unsafe.invokeCleaner(),它是 done in JogAmp's Gluegen .我更喜欢将 Cleaner 用作 Runnable,因为它避免依赖 sun.misc.Unsafe 但它现在不起作用。

我最后的建议适用于 Java 9、10、11 和 12 .

My very latest example需要使用孵化功能(需要 Java >= 14),但非常非常简单。

a good example in Lucene在更宽松的许可下。

关于java - 在 Java 中为 JOGL 释放直接缓冲区 native 内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3496508/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com