在Java中为JOGL释放直接缓冲区本机内存 [英] Deallocating Direct Buffer Native Memory in Java for JOGL

查看:85
本文介绍了在Java中为JOGL释放直接缓冲区本机内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using direct buffers (java.nio) to store vertex information for JOGL. These buffers are large, and they are replaced several times during the application life. The memory is not deallocated in time and I am running out of memory after a few replacements.

似乎没有好办法使用java.nio的缓冲区来解除分配。我的问题是:

It seems that there is not good way to deallocate using java.nio's buffer classes. My question is this:

JOGL中有一些方法可以删除Direct Buffers吗?我正在研究glDeleteBuffer(),但看起来这只是从显卡内存中删除缓冲区。

Is there some method in JOGL to delete Direct Buffers? I am looking into glDeleteBuffer(), but it seems like this only deletes the buffer from the video card memory.

谢谢

推荐答案

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

The direct NIO buffers use unmanaged memory. It means that they are allocated on the native heap, not on the Java heap. As a consequence, they are freed only when the JVM runs out of memory on the Java heap, not on the native heap. In other terms, it's unmanaged = it's up to you to manage them. Forcing the garbage collection is discouraged and won't solve this problem most of the time.

当你知道直接NIO缓冲区对你没用时,你必须通过使用sun.misc.Cleaner(StaxMan是正确的)释放其本机内存并调用clean()(使用Apache Harmony除外),调用free()(使用Apache Harmony)或使用更好的公共API来执行此操作(可能在Java> = 1.9,AutoCleaning扩展了AutoCloseable?)。

When you know that a direct NIO buffer has become useless for you, you have to release its native memory by using its sun.misc.Cleaner (StaxMan is right) and call clean() (except with Apache Harmony), call free() (with Apache Harmony) or use a better public API to do that (maybe in Java >= 1.9, AutoCleaning that extends AutoCloseable?).

这不是JOGL的工作,你可以使用普通的Java代码自己做。 我的例子属于GPL v2和这个例子是一个更宽松的许可证。

It's not JOGL job to do that, you can use plain Java code to do it yourself. My example is under GPL v2 and this example is under a more permissive license.

编辑:我的最新示例即使使用Java 1.9也支持OpenJDK, Oracle Java,Sun Java,Apache Harmony,GNU Classpath和Android。您可能必须删除一些语法糖,以使其适用于Java< 1.7(多次捕获,钻石和仿制药)。

Edit.: My latest example works even with Java 1.9 and supports OpenJDK, Oracle Java, Sun Java, Apache Harmony, GNU Classpath and Android. You might have to remove some syntactical sugar to make it work with Java < 1.7 (the multi catches, the diamonds and the generics).

参考: http://www.ibm.com/developerworks/library/j-nativememory-linux/

Direct ByteBuffer对象自动清理它们的本机缓冲区
但是只能作为Java堆GC的一部分 - 所以它们不会自动响应本机堆上的压力。当Java堆变得太满时,GC只发生
,它无法为堆分配
请求提供服务,或者Java应用程序显式请求它(不推荐使用
,因为它会导致性能问题)。

Direct ByteBuffer objects clean up their native buffers automatically but can only do so as part of Java heap GC — so they do not automatically respond to pressure on the native heap. GC occurs only when the Java heap becomes so full it can't service a heap-allocation request or if the Java application explicitly requests it (not recommended 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

此解决方案(在此 JEP 中,仍为草案,可能在Java 1.9中不可用)非常有前景,我们不需要使用非公共API。

This solution (in this JEP, still a draft, probably not available in Java 1.9) is very promising, we won't need to use non public APIs.

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();
    }
}

注意: sun.misc.Cleaner有被移动 jdk.internal.ref.Cleaner ,但后者实现了java.lang.Runnable(感谢Alan Bateman提醒我那个区别)。然后,您只需将清理器强制转换为Runnable并调用方法 run()(不要通过反射调用它以避免获取java.lang.IllegalAccessException )。它的工作原理,我刚刚使用Java 1.9 Early Access build 129进行了测试(2016年8月6日)。

N.B: sun.misc.Cleaner has been moved into jdk.internal.ref.Cleaner in Java 1.9 in the module "java.base" but the latter implements java.lang.Runnable (thanks to Alan Bateman for reminding me that difference). Then, you just have to cast the cleaner to a Runnable and to call the method run() (don't call it by reflection to avoid getting a java.lang.IllegalAccessException). It works, I've just tested (August, 6th, 2016) with Java 1.9 Early Access build 129.

但是,jdk.internal.ref.Cleaner可能会被移动to java.ref.Cleaner $ Cleanable later。

However, jdk.internal.ref.Cleaner might be moved to java.ref.Cleaner$Cleanable later.

在Lucene中的一个很好的例子,在更宽松的许可下。

There is a good example in Lucene under a more permissive license.

这篇关于在Java中为JOGL释放直接缓冲区本机内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆