JVM实战05(直接内存溢出)

2021/02/28 Jvm

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文件看不出问题或者比较小,可能是直接内存溢出问题。
配置内存时,如果有用到直接内存,应考虑设置直接内存合理大小值。

Search

    Table of Contents