【问题标题】:Are Java DirectByteBuffer wrappers garbage collected?Java DirectByteBuffer 包装器是否被垃圾收集?
【发布时间】:2011-10-05 13:52:04
【问题描述】:

我知道分配directbytebuffer时,它不受垃圾回收的影响,但我想知道包装对象是否被垃圾回收。

例如,如果我分配了一个新的 DirectByteBuffer dbb,然后使用 dbb.duplicate() 复制(浅复制)它,我将在同一块内存周围有两个包装器。

这些包装器会受到垃圾回收吗?如果我这样做了

while(true){
    DirectByteBuffer dbb2 = dbb.duplicate();
} 

我最终会自己 OOM 吗?

【问题讨论】:

  • 实际上,DirectByteBuffer 及其本机内存可能被垃圾回收。它使用 PhantomReference 来释放本地分配的内存。

标签: java garbage-collection bytebuffer


【解决方案1】:

查看DirectByteBuffer的源代码它只是返回一个新实例,所以不,你不会自己OOM。

只要您的其余代码不保留对原始dbb 的引用,那么该对象将正常进行垃圾收集。额外的dbb2 对象在不再有任何引用时(即while 循环结束)同样会被垃圾回收。

【讨论】:

    【解决方案2】:

    直接的ByteBuffer 对象与任何其他对象一样:它可以被垃圾回收。

    ByteBuffer对象被GC'd时,直接缓冲区使用的内存将被释放(ByteBuffer没有明确说明,但MappedByteBuffer的文档暗示了这一点)。

    有趣的是,当您使用直接缓冲区填充了虚拟内存空间,但堆中仍有大量空间时。事实证明(至少在 Sun JVM 上),在分配直接缓冲区时耗尽虚拟空间将触发 Java 堆的 GC。这可能会收集未引用的直接缓冲区并释放它们的虚拟内存承诺。

    如果你在 64 位机器上运行,你应该使用-XX:MaxDirectMemorySize,它为你可以分配的缓冲区数量设置了一个上限(当你达到这个限制时也会触发 GC)。

    【讨论】:

    • 使用 DirectByteBuffers 对垃圾收集暂停有何帮助,比如 TerraCotta 的 BigMemory?
    • @李皮:因为你可以在一个直接缓冲区中存储大量序列化的Java对象。
    【解决方案3】:

    在 Sun JDK 中,java.nio.DirectByteBuffer(由 ByteBuffer#allocateDirect(int) 创建)具有类型为 sun.misc.Cleaner 的字段,该字段扩展了 java.lang.ref.PhantomReference

    当这个Cleaner(记住,PhantomReference 的子类型)被收集并即将移动到关联的ReferenceQueue 时,运行在嵌套类型ReferenceHandler 中的与收集相关的线程有一个特殊的情况处理Cleaner 实例:它向下转换并调用Cleaner#clean(),最终返回调用DirectByteBuffer$Deallocator#run(),而后者又调用Unsafe#freeMemory(long)。哇。

    这是相当迂回的,我很惊讶没有看到Object#finalize() 的任何使用。 Sun 开发人员一定有他们的理由将其与收集和引用管理子系统联系得更紧密。

    简而言之,你不会因为放弃对DirectByteBuffer 实例的引用而耗尽内存,只要垃圾收集器有机会注意到放弃并且它的引用处理线程通过上述调用取得进展.

    【讨论】:

    • 请注意,如果您使用的是-XX:+DisableExplicitGC,那么您可能会遇到更多带有allocateDirectOutOfMemory 错误。分配尝试保留内存并调用System.gc(),如果它不能触发PhantomReference 的回收。
    【解决方案4】:

    当分配一个directbytebuffer时,它不会受到垃圾的影响 收藏

    你是从哪里得到这个想法的?这是不正确的。您是否将它们与 MappedByteBuffers 混淆了?

    【讨论】:

      猜你喜欢
      • 2011-01-26
      • 2020-02-11
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多