Netty之堆外内存

时间:2022-07-28 15:13:03

堆外内存定义: Java.nio.DirectByteBuffer所占用的内存,我们常说的堆外内存溢出就是指Java.nio.DirectByteBuffer所需的内存超过了物理分配的堆外内存,出现”java.lang.OutOfMemoryError: Direct buffer memory”。

显示设置堆外内存: 通过JVM参数 -XX:MaxDirectMemorySize 来指定最大的堆外内存;

堆外内存默认值: (-Xmx值) - (1个survivor大小)

堆外内存优缺点:
  优点: 避免了数据的多次拷贝(IO通信时,如果数据是在堆内的,会先拷贝一份到堆外,然后再进行发送)、访问速度快;
  缺点:分配和回收堆外内存比分配和回收堆内存耗时;

堆外内存的回收:
  JDK中使用DirectByteBuffer对象来表示堆外内存,每个DirectByteBuffer对象在初始化时,都会创建一个对用的Cleaner对象,这个Cleaner对象会在合适的时候执行unsafe.freeMemory(address),从而回收这块堆外内存。
  主动回收(推荐): 对于Sun的JDK,只要从DirectByteBuffer里取出那个sun.misc.Cleaner,然后调用它的clean()就行;
  基于 GC 回收:堆内的DirectByteBuffer对象被GC时,会调用cleaner回收其引用的堆外内存。问题是YGC只会将将新生代里的不可达的DirectByteBuffer对象及其堆外内存回收,如果有大量的DirectByteBuffer对象移到了old区,但是又一直没有做CMS GC或者FGC,而只进行YGC,那么我们的物理内存可能被慢慢耗光;