JVM实战05(直接内存溢出)
目录
直接内存
1.java虚拟机规范并没有定义这块区域
2.不属于虚拟机运行时数据区
3.直接内存是一快由操作系统管理的内存,也叫堆外内存
4.可以使用Unsafe或ByteBuffer分配直接内存
5.可以用-XX:MaxDirectMemorySize控制,默认是0,表示不限制:
a.无法控制Unsafe类
b.可以影响ByteBuffer
6.为什么要由直接内存?主要是性能优势,直接内存速度快的多,
IO效率高。
直接内存使用场景
频繁的IO操作,比如并法网络通信。(java的NIO使用了直接内存)
有很的数据需要存储,生命周期很长。
分配直接内存
1.Unsafe.allocateMemory(size) // Unsafe类,在netty里也用到了,不过JDK11后的版本不建议使用
2.ByteBuffer.allocateDirect(size) //netty里用到了ByteBuffer
直接内存溢出实战
public class OOMTest
{
public static final int GB_SIZE = 1024 * 1024 * 1024;
public static void main(String[] args) throws IllegalAccessException {
//通过反射获取Unsafe类并通过分配直接内存
Field declaredField = Unsafe.class.getDeclaredFields()[0];
declaredField.setAccessible(true);
Unsafe unsafe = (Unsafe) declaredField.get(null);
int i = 0;
while (true)
{
unsafe.allocateMemory(GB_SIZE);
System.out.println(++i);
}
}
}
上述代码,利用Unsafe类不停的在死循环里直接分配内存,运行一段时间后报错:
运行次数:18
java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at org.game.OOMTest.main(OOMTest.java:21)
1.OutOfMemoryError没有详细报哪个地方内存溢出。
2.如果增加设置-XX:MaxDirectMemorySize参数,但运行次数还是18,
不对Unsafe类起作用。
public class OOMTest
{
public static final int GB_SIZE = 1024 * 1024 * 1024;
public static void main(String[] args){
int i = 0;
while (true)
{
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(GB_SIZE);
System.out.println(++i);
}
}
}
上述代码,利用ByteBuffer类不停的在死循环里直接分配内存,运行一段时间后报错:
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at org.game.OOMTest.main(OOMTest.java:17)
1.OutOfMemoryError有详细报哪个地方内存溢出:Direct buffer memory。
2.如果增加设置-XX:MaxDirectMemorySize=1m参数一下子内存不够,直接报错,
说明参数对ByteBuffer类有效。
直接内存溢出可能情况
堆Dump文件看不出问题或者比较小,可能是直接内存溢出问题。
配置内存时,如果有用到直接内存,应考虑设置直接内存合理大小值。