Java DirectByteBuffer包装器是否被垃圾收集?
我知道,当分配directbytebuffer时,它不会被垃圾收集,但我想知道的是包装对象是否被垃圾收集 例如,如果我分配了一个新的DirectByteBuffer dbb,然后使用dbb.duplicate()对其进行复制(浅复制),那么在同一内存块上会有两个包装器 那些包装纸要接受垃圾收集吗?如果我有Java DirectByteBuffer包装器是否被垃圾收集?,java,garbage-collection,bytebuffer,Java,Garbage Collection,Bytebuffer,我知道,当分配directbytebuffer时,它不会被垃圾收集,但我想知道的是包装对象是否被垃圾收集 例如,如果我分配了一个新的DirectByteBuffer dbb,然后使用dbb.duplicate()对其进行复制(浅复制),那么在同一内存块上会有两个包装器 那些包装纸要接受垃圾收集吗?如果我有 while(true){ DirectByteBuffer dbb2 = dbb.duplicate(); } 我最终会自己OOM吗?查看DirectByteBuffer的源代码,
while(true){
DirectByteBuffer dbb2 = dbb.duplicate();
}
我最终会自己OOM吗?查看DirectByteBuffer的源代码,它只返回一个新实例,所以不,你不会自己OOM
只要代码的其余部分没有保留对原始
dbb
的引用,那么该对象将正常地被垃圾收集。额外的dbb2
对象在不再有任何引用(即while循环的结束)时也会被垃圾收集。直接ByteBuffer
对象与任何其他对象一样:它可以被垃圾收集
当ByteBuffer
对象为GC'd时,直接缓冲区使用的内存将被释放(这不是为ByteBuffer
明确规定的,而是在MappedByteBuffer
的文档中暗示的)
有趣的是,当您用直接缓冲区填充了虚拟内存空间,但堆中仍然有很多空间时。事实证明(至少在Sun JVM上),在分配直接缓冲区时耗尽虚拟空间将触发Java堆的GC。它可以收集未引用的直接缓冲区并释放其虚拟内存
如果您在64位计算机上运行,您应该使用
-XX:MaxDirectMemorySize
,这会对您可以分配的缓冲区数量设置上限(并且在达到该限制时还会触发GC)。在Sun JDK中,由创建的java.nio.DirectByteBuffer
-有一个类型为Sun.misc.Cleaner
的字段,这延伸了
当收集此清理器
(请记住,PhantomReference
的子类型)并即将移动到关联的引用队列
,通过嵌套类型ReferenceHandler
运行的与集合相关的线程对Cleaner
实例有一个特殊的案例处理:它向下转换并调用Cleaner#clean()
,最终返回到调用DirectByteBuffer$Deallocator#run()
,这反过来会调用不安全#空闲内存(long)
。哇
它相当迂回,我很惊讶没有看到Object\finalize()
的任何使用。Sun开发人员一定有理由将其与收集和引用管理子系统更紧密地联系在一起
简而言之,只要垃圾回收器有机会注意到放弃,并且其引用处理线程通过上述调用取得进展,就不会因为放弃对DirectByteBuffer
实例的引用而耗尽内存
分配directbytebuffer时,它不受垃圾的约束
收藏
你从哪里得到这个主意的?这是不对的。你把它们和MappedBytebuffer混在一起了吗?实际上,DirectByteBuffer及其本机内存可能会被垃圾收集。它使用PhantomReference释放本机分配的内存。使用DirectByteBuffers如何帮助垃圾收集暂停,ala TerraCotta的BigMemory?@Li Pi:因为您可以在一个直接缓冲区中存储大量序列化Java对象。请注意,如果您使用
-XX:+DisableExplicitGC
,那么您可能会遇到更多OutOfMemory
错误。分配尝试保留内存,若不能,则调用System.gc()
,以触发PhantomReference
的回收。