JVM中OOM常见几种类型

Java中的OOM

  • java.lang.StackOverflowError
  • java.lang.OutMemoryError:Java heap space
  • java.lang.OutMemoryError:GC overhead limit exceeded:Gc回收时间过长会发生outofmemoryerror,过长的定义是,如果超过98%的时间来做GC,并且回收了不到2%的堆内存,连续多次回收不到2%的情况会跑出,负责形成恶性循环,gc清理的内存再次被填满,迫使gc再次执行。
        /*
        -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
         */
        public static void main(String[] args){
    
            int i = 0;
            List<String> list = new ArrayList<>();
    
            try{
                while (true){
                    list.add(String.valueOf(new Random().nextInt(1111111)).intern());
                }
            }catch (Throwable e){
                e.printStackTrace();
            }
        }
  • java.lang.OutMemoryError:Direct buffer memory:写NIO程序使用ByteBuffer来读取或者写入数据,这是基于通道(channel)和缓冲区(buffer)的IO方式,可以使用Native函数库直接分配堆内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,这样在一些场景中能够提高性能,避免了Java堆和native堆中来回复制数据。
    • ByteBuffer.allocate(capability)第一种方式分配JVM内存,属于GC管辖范围,需要拷贝所以速度相对较慢
    • ByteBuffer.allocateDirect(capability)第二种方式分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝,故而速度较快
          /*
          -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
           */
          static void directMemory(){
      
              System.out.println("配置的MaxDirectMemory:" + sun.misc.VM.maxDirectMemory()/ (double)1024 / 1024 + "MB");
      
              ByteBuffer.allocateDirect(6 * 1024 * 1024);
          }
  • java.lang.OutMemoryError:unable to create new native thread:在高并发请求服务器的时候,一个应用进程创建太多线程,超过系统的承载能力。你的服务器不允许应用程序创建这么多线程,Linux系统默认一个进程可以创建最多1024个线程(解决办法:减少线程创建或者修改默认服务器配置,扩大默认限制)。
  • java.lang.OutMemoryError:Metaspace:java8metaspace取代永久代,使用本地内存进行存储。Metaspace是方法与在HotSpot中的实现,即在java8中,classe metadata被存储在Metaspace的native memory(永久代/metaspace:虚拟机加载的类型学,常量池,静态变量,即时编译后的代码)

猜你喜欢

转载自www.cnblogs.com/shemlo/p/11665917.html