Java 我们必须手动释放已分配的ByteBuffer吗?

Java 我们必须手动释放已分配的ByteBuffer吗?,java,lwjgl,nio,Java,Lwjgl,Nio,我正在写一些使用ByteBuffers的东西。上面说 没有办法显式释放缓冲区(没有JVM特定的 反射)缓冲区对象受GC约束,通常需要两个 GC循环以在缓冲区对象变为空后释放堆外内存 遥不可及 然而,在一篇文章中,我读到 BigMemory通过direct使用JVM进程的内存地址空间 与其他本机Java不同,不受GC约束的字节缓冲区 对象 现在我应该怎么做,我应该释放创建的缓冲区吗?还是我误解了文档或答案中的某些内容?这取决于您如何创建缓冲区,有许多可能的用例。常规ByteBuffer.alloc

我正在写一些使用
ByteBuffer
s的东西。上面说

没有办法显式释放缓冲区(没有JVM特定的 反射)缓冲区对象受GC约束,通常需要两个 GC循环以在缓冲区对象变为空后释放堆外内存 遥不可及

然而,在一篇文章中,我读到

BigMemory通过direct使用JVM进程的内存地址空间 与其他本机Java不同,不受GC约束的字节缓冲区 对象


现在我应该怎么做,我应该释放创建的缓冲区吗?还是我误解了文档或答案中的某些内容?

这取决于您如何创建缓冲区,有许多可能的用例。常规
ByteBuffer.allocate()
将在堆上创建,并由GC收集。其他选项(如本机内存)可能不会

Terracotta BigMemory是一种不受JVM GC控制的本机堆外内存。如果您在这种类型的内存中分配了一个缓冲区,您必须自己清除它


清除缓冲区可能是一个好主意,即使缓冲区是在堆内存中分配的。GC将负责收集未使用的缓冲区,但这将需要一些时间。

正如LWJGL中
BufferUtils
的文档所述:没有办法显式释放
ByteBuffer

使用标准机制分配的
ByteBuffer
对象(即,通过直接或间接调用
ByteBuffer#allocateDirect
)受GC约束,最终将被清除

您链接到的答案似乎特别指的是BigMemory库。使用JNI,您可以创建一个(直接的)
ByteBffer
,它不是由GC处理的,并且由您实际释放底层数据


但是,有一个简短的建议:在处理LWJGL和其他依赖(直接)
ByteBuffer
对象将数据传输到本机端的库时,应该考虑这些缓冲区的使用模式。特别是对于OpenGL绑定库,您经常需要一个
字节缓冲区
,该缓冲区只能容纳16个
float
值(例如,包含发送给OpenGL的矩阵)。在许多情况下,使用这些缓冲区进行数据传输的方法将被频繁调用

在这种情况下,反复分配这些小型、短期缓冲区通常不是一个好主意:

class Renderer {
    void renderMethodThatIsCalledThousandsOfTimesPerSecond() {
        ByteBuffer bb = ByteBuffer.allocateDirect(16 * 4);
        fill(bb);
        passToOpenGL(bb);
    }
}
创建这些缓冲区和GC会显著降低性能,令人不安的是GC暂停会导致游戏延迟

对于这种情况,退出分配并重新使用缓冲区是有益的:

class Renderer {

    private final ByteBuffer MATRIX_BUFFER_4x4 = ByteBuffer.allocateDirect(16 * 4);

    void renderMethodThatIsCalledThousandsOfTimesPerSecond() {
        fill(MATRIX_BUFFER_4x4);
        passToOpenGL(MATRIX_BUFFER_4x4);
    }
}

谢谢,但是混淆的原因是通过直接ByteBuffers的部分不受GC的约束。那么兵马俑BM使用的
ByteBuffer
s有什么不同?或者他们的名字只是巧合?请仔细阅读:行。谷歌爸爸首先弹出了文档,然后是一些SO帖子,这引起了误解,因此产生了问题。这是很好的,有这个链接在这里为我和任何其他人谁可能偶然发现这篇文章。感谢你的回答,这是非常值得一提的性能原因。现在我只是在Java代码中使用assimp,但我担心内存泄漏。