【问题标题】:java.nio.ByteBuffer - allocateDirect and garbage collectionjava.nio.ByteBuffer - allocateDirect 和垃圾回收
【发布时间】:2015-12-04 17:39:46
【问题描述】:
我今天读到以下内容:
Direct ByteBuffer 对象自动清理它们的本地缓冲区
但只能作为 Java 堆 GC 的一部分这样做——所以它们不会
自动响应本机堆上的压力。 GC 只发生
当 Java 堆变得如此满时,它无法为堆分配提供服务
请求,或者如果 Java 应用程序显式请求它(不是
推荐,因为它会导致性能问题)。
我的印象是,使用 Direct ByteBuffers 意味着您必须手动管理本机内存的分配/解除分配,并且它根本不受 GC 的影响。但是这篇文章似乎说如果 GC 确实发生,那么直接 ByteBuffer 会被收集。
我认为在进行堆外存储时,主要动机之一是避免因 GC 可能出现的问题(例如长时间停顿)。
【问题讨论】:
标签:
java
garbage-collection
【解决方案1】:
DirectByteBuffer 对象是非常小的对象,基本上只是保存一个指向本机内存的指针。这允许在不扩展托管堆和零拷贝 IO 的情况下进行分配。
所以这些对象一般不会增加多少 GC 压力。
它们消耗的是本地资源、虚拟地址空间以及可能的物理内存或交换空间。如果您使用的是内存映射文件而不是 allocateDirect 创建的缓冲区,您可能会大大超过可用的物理内存,因为内存将由磁盘存储支持(类似于交换)。
你唯一不能做的事情,至少通过官方 API 是取消映射直接缓冲区指向的内存范围。相反,一旦缓冲区本身被 GC 收集,底层内存就会被释放。
TL;DR:您无法获得完全手动的内存管理,但您确实摆脱了托管 Java 堆的一些限制。