怎么样会用到直接内存?
1.Unsafe类
比较危险 不推荐使用的
但是强行要用的话 可以反射来用
public class UnsafeDemo {
public static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
long addr = unsafe.allocateMemory(100*_1MB);
}
}
危险 ! 非正常用法!
加上直接内存的限制参数 -XX:MaxDirectMemorySize=10m
完全没生效! 法外之地!
2. ByteBuffer类
Netty 的直接内存,ByteBuffer
底层会调用操作系统的 malloc 函数。
正常用户
ByteBuffer.allocateDirect(128*1024*1024);
这种是可以被 -XX:MaxDirectMemorySize=10m
这样限制的
3.Native方法
JNI 或者 JNA 程序,直接操纵了本地内存,比如一些加密库
记得close, 就可以避免内存泄漏
直接内存优缺点
优点
- 不在堆里面, 当然不用垃圾回收了
- 本来要刷到写缓存也要先到直接内存, 省了这步从堆到直接内存的复制
- 可以用直接内存 ,做jvm进程间的共享
- 更大!
缺点
- 内存泄漏难查了
- 只能 存byte[], 存复杂对象比较麻烦
内存泄漏了, 几乎根本查不出来
故意不close
public static String decompress(byte[] input) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(input));
try {
copy(gzip, out);
return new String(out.toByteArray());
}finally {
try{
//gzip.close();
}catch (Exception ex){
}
try{
out.close();
}catch (Exception ex){
}
}
}
top
命令查看

看看是不是堆太大了
jmap –heap

只有300多M 明细不的堆占用的 1.5G 这么大
jmap -histo 进程| head -20
看看 占最多的对象

最多也就20M
那再看看是不是栈 占用的
jstack 进程号

也就十来个线程
每个1M , 一共十几M
只能反省,哪里没close
直接内存的大小限制
可以用-XX:MaxDirectMemorySize
限制 正常分配的直接内存大小
如果不设 默认是 等于
新生代的最大值 = 新生代的最大值 - 一个 survivor
就是
-Xmx 减去 一个survivor
网友评论