【问题标题】:Java - When does direct buffer released?Java - 何时释放直接缓冲区?
【发布时间】:2016-07-04 19:26:17
【问题描述】:

既然已经用jvm heap & gc了,什么时候发布呢?或者,它会一直保留到进程终止?

我已经检查过了:

但是所有的答案都是模糊的,没有一个明确的回答,有明确的答案吗?至少对于 64 位 Linux 上的 Java 8

【问题讨论】:

  • ByteBuffer 被垃圾回收时,终结器将执行并释放任何底层内存分配。
  • 由于你不能保证它会被释放,我建议你自己处理它,我从JM3中为我的项目剥离了BufferUtils类,比如@987654325 @,直到现在它完美无缺
  • @elect 是的,有些书还说它适用于大而长的缓冲区,因此分配延迟的影响较小。对于小而短暂的缓冲区,建议不要使用direct buffer,而是使用indirect buffer
  • 如果资源将被 OpenGL 使用,缓冲区必须是间接的。如果你传递一个间接的,jogl 必须在下面创建直接的。如果是你创造的,那就更好了,这样你就可以跟踪它。
  • @elect 好的,我会记住这种情况的存在。

标签: java nio bytebuffer direct-buffer


【解决方案1】:

DirectByteBuffer 不使用旧的 Java 终结器。相反,它使用内部sun.misc.Cleaner API。它创建新线程并将PhantomReference 存储到每个创建的DirectByteBuffer(引用主缓冲区的重复项和切片除外)。当DirectByteBuffer 变为phantom-reachable(即不再存在对字节缓冲区的强、软或弱引用)并且垃圾收集器看到这一点时,它将这个缓冲区添加到ReferenceQueueCleaner 线程处理。所以应该发生三个事件:

  • DirectByteBuffer 变为幻象可达。
  • 执行垃圾收集(在单独的线程中),收集DirectByteBuffer Java 对象并将一个条目添加到ReferenceQueue
  • 清理线程到达该条目并运行注册的清理动作(在本例中为java.nio.DirectByteBuffer.Deallocator 对象),该动作最终释放本机内存。

因此,通常您无法保证何时释放它。如果 Java 堆中有足够的内存,垃圾收集器可能会很长时间没有被激活。此外,即使它是幻象可访问的,Cleaner 线程也可能需要一些时间才能到达此条目。它可能正忙于处理也使用 Cleaner API 的先前对象。但是请注意,部分解决方法是在 JDK 中实现的:如果您创建新的 DirectByteBuffer 并在之前分配了过多的直接内存,则可能会显式调用垃圾收集器以强制释放以前放弃的缓冲区。详见Bits.reserveMemory()(从DirectByteBuffer构造函数调用)。

请注意,在 Java-9 中,内部 Cleaner API 已被纠正并发布以供一般使用:现在它是 java.lang.ref.Cleaner。阅读 JavaDoc,您可能会获得更多详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    相关资源
    最近更新 更多