spa*_*400 14 java buffer memory-management nio jogl
我使用直接缓冲区(java.nio)来存储JOGL的顶点信息.这些缓冲区很大,在应用程序生命周期中它们会被更换几次.内存未及时解除分配,并且在几次更换后我的内存不足.
似乎没有好的方法来释放使用java.nio的缓冲区类.我的问题是:
JOGL中有一些方法可以删除Direct Buffers吗?我正在研究glDeleteBuffer(),但似乎这只是从显卡内存中删除缓冲区.
谢谢
gou*_*sej 16
直接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(多捕获,钻石和泛型)一起使用.
参考: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();
}
}
Run Code Online (Sandbox Code Playgroud)
注:sun.misc.Cleaner已被移动到jdk.internal.ref.Cleaner在模块"java.base",但后者农具了java.lang.Runnable(感谢艾伦·贝特曼提醒我说,差)在Java中1.9.然后,您只需将清理器强制转换为Runnable并调用该方法__CODE__
(不要通过反射调用它以避免获得java.lang.IllegalAccessException).它的工作原理,我刚刚使用Java 1.9 Early Access build 129进行了测试(2016年8月6日).
但是,jdk.internal.ref.Cleaner可能会在以后转移到java.ref.Cleaner $ Cleanable.