jvm Java GC如何执行直接字节缓冲区清理,因为IBM文档说,它可以,

kadbb459  于 2022-11-07  发布在  Java
关注(0)|答案(4)|浏览(164)

我以为,我理解如何Bytebuffer和DirectByteBuffer的区别,直到我读了一篇文章的IBM文档,提出:
“直接ByteBuffer对象自动清除其本机缓冲区,但只能作为Java堆GC的一部分执行此操作”
https://www.ibm.com/developerworks/library/j-nativememory-linux/
现在我不能理解这一行,因为它说DirectByteBuffer作为Java堆GC的一部分进行清理。
IFAIK,Java堆GC只在Java堆中进行清理(其中未分配DirectByteBuffer)。它(GC)不知道本机内存(其中分配了DirectByteBuffer)。
请帮助我理解这一行,或者如果我理解有差距

n6lpvg4x

n6lpvg4x1#

当您创建java.nio.DirectByteBuffer的示例时,实际上有两个部分:

  • 类型为java.nio.DirectByteBuffer的普通java对象,在堆上分配
  • 所需的实际字节缓冲区,它由上述java对象的构造函数从堆中分配

另外,java.nio.DirectByteBuffer的构造函数注册了一个java.nio.DirectByteBuffer.Deallocator类型的runnable,它是一个私有静态类。当java.nio.DirectByteBuffer的示例被GC清理时,这个runnable就会被执行。Deallocator的任务就是释放本机字节缓冲区。RTFS!:)

vu8f3i0k

vu8f3i0k2#

对于11(可能是更高),在GC检测到DirectByteBuffer已变为幻影可达之后的某个时间,引用处理程序线程将运行DirectByteBuffer中的清除代码,该代码将释放本机内存区域。
您可以通过调用Unsafe来自己调用清理,如下所示:

Unsafe u = Unsafe.getUnsafe()
ByteBuffer bb = ByteBuffer.createdDirect(100);
u.invokeCleaner(bb);

我确实觉得,如果可以的话,应该避免做这一切。

q3qa4bjr

q3qa4bjr3#

Java堆GC仅在Java堆中执行清除
在HotSpot JVM中,清除DirectByteBuffer时,会释放或取消Map与相关联的内存。
注意:这与作为外部资源(如套接字、文件流、GUI组件)的代理的其他对象没有什么不同。
不同的是资源不是Closeable的。这可能是由于多种原因而不可用的,最有可能的原因是在内存区域被释放后访问它可能会损坏内存或使JVM崩溃。使用Hotspot JVM,可以使用

((DirectBuffer) buffer).cleaner().clean();

但是,这是未记录的,并且a)不同JVM之间不相同,B)使用风险自担,c)将来可能不可用。

lg40wkob

lg40wkob4#

它说DirectByteBuffer将清理作为Java堆GC的一部分。
不,它没有。它说“直接ByteBuffer对象自动清理它们的本机缓冲区,但 * 只能 * 作为Java堆GC的一部分这样做”。完全不是一回事。
IFAIK、Java堆GC仅在Java堆中执行清理
正确,但是IBM说的是直接用ByteBuffers进行清理,而不是用GC。
(其中DirectByteBuffer未分配)。
没有DirectByteBuffer这样的东西,有直接的ByteBuffers,它们 * 是 * 在堆上分配的,除了它们的直接部分,这是一个本机字节数组。
它(GC)不知道本机内存(分配DirectByteBuffer的地方)。
又错了,见上文。
这并不神秘。直接ByteBuffers可以有一个finalize()方法,当被GC调用时,该方法调用本机字节数组的清理。

相关问题