直接内存(堆外内存)(gold_axe)

2020-09-30  本文已影响0人  胖达_4b7e

怎么样会用到直接内存?

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, 就可以避免内存泄漏

直接内存优缺点

优点

缺点

内存泄漏了, 几乎根本查不出来

故意不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

上一篇 下一篇

猜你喜欢

热点阅读