堆外内存: 不进行GC,防止JNI访问错位。
使用方式
使用堆外内存的两种方式:
1.隐式:比如读写文件时:
读文件: 文件(disk)=>堆外内存=>堆内内存;(过程中JVM保证不GC)
写文件: 堆内内存=>堆外内存=>文件(disk)。
2.显式:使用DirectByteBuffer
,直接在堆外分配空间,节省1倍空间,减去一倍拷贝操作。
1 | // 底层源码: |
Unsafe
java直接管理内存用的类,之所以叫Unsafe
,意思是这些原来设计是给sun公司的人专用的,不是开放给外面的人用的,希望普通用户不要依赖它的接口,随时随着jdk版本升级而更改接口。// 如果不升级jdk,就不用care了。
并不是说这个类不安全。
使用场景
(因为不gc)
生命期较长的大对象;
创建次数不会太多。
// 如直接的文件拷贝操作。
优点
1.对于大内存有良好的伸缩性
2.对垃圾回收停顿的改善可以明显感觉到
3.在进程间可以共享,减少虚拟机间的复制
配置
1 | -XX:MaxDirectMemorySize |
堆外内存回收
三种方法:
1.达到限制触发自动回收;(system.gc()
) // 可能被配置-XX:+DisableExplicitGC
关闭。
2.手动调用Unsafe
的freeMemory
接口。
3.使用DirectByteBuffer
,它在初始化的时候会创建Cleaner
这个Cleaner对象会在合适的时候执行unsafe.freeMemory(address)
,从而回收这块堆外内存。
4.手动调用((DirectBuffer)bb).cleaner().clean();
.
// 内部还是调用System.gc()
,所以一定不要-XX:+DisableExplicitGC
。
相关代码:
1 | private static class Deallocator implements Runnable { |