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,但我担心内存泄漏。