06–内存区域–直接内存
1、结构图
2、直接内存(堆外内存)
1、 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中农定义的内存区域;
2、 在JDK1.4中新加入了NIO(NewInput/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用native函数库直接分配堆外内存(直接内存),然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据;
3、 本机直接内存的分配不会受到Java堆大小的限制,受到本机总内存大小限制;
4、 配置虚拟机参数时,不要忽略直接内存,防止出现OutOfMemoryError异常;
2.1、 直接内存(堆外内存)与堆内存比较
1、 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显;
2、 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显;
2.2、 直接内存使用场景
1、 有很大的数据需要存储,它的生命周期很长;
2、 适合频繁的IO操作,例如网络并发场景;
2.3、 内存溢出案例
package com.fei.zhou.day1;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class DirectMemoryOOMTest {
/**
* VM Args:-Xms20m -Xmx20m -XX:MaxDirectMemorySize=10m
* @param args
*/
public static void main(String[] args) {
int i=0;
try {
Field field = Unsafe.class.getDeclaredFields()[0];
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
while(true){
//申请内存1M
unsafe.allocateMemory(1024*1024);
i++;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("分配次数:"+i);
}
}
}
结果:
分配次数:9639
Exception in thread "main" java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at com.fei.zhou.day1.DirectMemoryOOMTest.main(DirectMemoryOOMTest.java:21)