Sta*_*Man 21 java memory garbage-collection memory-management
JDK提供了分配所谓的直接ByteBuffers的能力,其中内存在Java堆之外分配.这可能是有益的,因为垃圾收集器不会触及这个内存,因此不会导致GC开销:这对于像缓存这样的长期存在的东西来说非常有用.
但是,现有实现存在一个关键问题:当拥有ByteBuffer被垃圾收集时,底层内存只是异步分配; 没有办法强迫早期解除分配.这可能有问题,因为GC循环本身不受ByteBuffers处理的影响,并且假设ByteBuffers可能驻留在Old Generation内存区域,则可能在ByteBuffer不再使用后几小时调用GC.
但理论上应该可以直接使用sun.misc.Unsafe方法(freeMemory,allocateMemory):这就是JDK本身用于分配/解除分配本机内存的方法.看一下代码,我看到的一个潜在问题是内存双重释放的可能性 - 所以我想确保正确清理状态.
任何人都可以指向我这样做的代码吗?理想情况下,想要使用它而不是JNA.
注意:我看到这个问题有点相关.
看起来指出的答案是很好的方法:这里是使用这个想法的Elastic Search的代码示例.谢谢大家!
Pet*_*rey 25
有一种更简单的清理内存的方法.
public static void clean(ByteBuffer bb) {
if(bb == null) return;
Cleaner cleaner = ((DirectBuffer) bb).cleaner();
if (cleaner != null) cleaner.clean();
}
Run Code Online (Sandbox Code Playgroud)
如果你相当快地丢弃直接或内存映射的ByteBuffer,使用它可以产生很大的不同.
使用Cleaner执行此操作的原因之一是您可以拥有底层内存资源的多个副本,例如slice().清洁工具有这些资源数量.
sun.misc.Unsafe几乎不可能使用,因为分配的本机内存的基址是java.nio.DirectByteBuffer构造函数的局部变量.
实际上,您可以使用以下代码强制释放本机内存:
import sun.misc.Cleaner;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
...
public static void main(String[] args) throws Exception {
ByteBuffer direct = ByteBuffer.allocateDirect(1024);
Field cleanerField = direct.getClass().getDeclaredField("cleaner");
cleanerField.setAccessible(true);
Cleaner cleaner = (Cleaner) cleanerField.get(direct);
cleaner.clean();
}
Run Code Online (Sandbox Code Playgroud)