OOM 6

  1. java.lang.StackOverflowError
  2. java.lang.OutOfMemoryError: Java Heap Space
  3. java.lang.OutOfMemoryError: GC overhead limit exceeded
  4. java.lang.OutOfMemoryError: Direct buffer memory
  5. java.lang.OutOfMemoryError: unable to create new native thread
  6. java.lang.OutOfMemoryError: Metaspace

easy:

  1. java.lang.StackOverflowError: 栈递归调用过深
  2. java.lang.OutOfMemoryError: Java Heap Space: heap因为new对象过多撑爆

GC overhead limit exceeded

GC overhead limit exceeded Demo

VM options:

-Xmx5m -Xmx5m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m

java.lang.OutOfMemoryError: GC overhead limit exceeded: 多: heap中的对象都不同intern() 并且有引用,CPU >98%全部耗在GC上,但是GC实际上并没有什么卵用。

[Full GC (Ergonomics) [PSYoungGen: 1024K->1024K(1536K)] [ParOldGen: 4030K->4030K(4096K)] 5054K->5054K(5632K), [Metaspace: 3218K->3218K(1056768K)], 0.0186593 secs] [Times: user=0.10 sys=0.00, real=0.02 secs] 
.....
[Full GC (Ergonomics) [PSYoungGen: 1024K->0K(1536K)] [ParOldGen: 4041K->474K(4096K)] 5065K->474K(5632K), [Metaspace: 3218K->3218K(1056768K)], 0.0046420 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
************i777
Heap
 PSYoungGen      total 1536K, used 161K [0x00000007bfe00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1024K, 15% used [0x00000007bfe00000,0x00000007bfe28a80,0x00000007bff00000)
  from space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
  to   space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
 ParOldGen       total 4096K, used 474K [0x00000007bfa00000, 0x00000007bfe00000, 0x00000007bfe00000)
  object space 4096K, 11% used [0x00000007bfa00000,0x00000007bfa76b38,0x00000007bfe00000)
 Metaspace       used 3256K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 354K, capacity 388K, committed 512K, reserved 1048576K
java.lang.OutOfMemoryError: GC overhead limit exceeded
...

NIO: Direct Buffer Memory (直接内存溢出)

写NIO的程序经常用ByteBuffer读取/写入数据,这是一种基于通道(Channel)和缓冲区(buffer)的IO方式;ByteBuffer可以直接分配堆外内存,然后通过JVM堆内DirectByteBuffer对象作为这个对象的引用。因为NIO是要从物理内存出去,直接分配在堆外:避免了Java堆和Native堆中来回分配数据,显著提高性能。

  • ByteBuffer.allocate(capacity): 1. 分配JVM堆内存,属于GC,因为需要拷贝所以慢
  • ByteBuffer.allocateDirect(capa): 2. 分配OS本地内存,不属于GC,不需要内存拷贝,所以快

但是如果不断分配本地内存,堆内存很少使用,那么JVM就不GC,DirectByteBuffer 对象们就不会被回收;

这个时候堆内存充足,但是本地内存可能用光了,地基不稳,再次尝试分配本地内存就OOM了
DirectBufferMemoryDemo

[GC (Allocation Failure) [PSYoungGen: 1024K->480K(1536K)] 1024K->480K(5632K), 0.0009465 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
配置的maxDirectMemory:5.0MB
[GC (System.gc()) [PSYoungGen: 1315K->496K(1536K)] 1315K->576K(5632K), 0.0008687 secs] [Times: user=0.00 sys=0.01, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 496K->0K(1536K)] [ParOldGen: 80K->457K(4096K)] 576K->457K(5632K), [Metaspace: 3115K->3115K(1056768K)], 0.0046424 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Bits.java:694)
    at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
    at com.lei.concurrentandjvm.oom.DirectBufferMemoryDemo.main(DirectBufferMemoryDemo.java:28)
Heap
 PSYoungGen      total 1536K, used 104K [0x00000007bfe00000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1024K, 10% used [0x00000007bfe00000,0x00000007bfe1a070,0x00000007bff00000)
  from space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000)
  to   space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
 ParOldGen       total 4096K, used 457K [0x00000007bfa00000, 0x00000007bfe00000, 0x00000007bfe00000)
  object space 4096K, 11% used [0x00000007bfa00000,0x00000007bfa727b8,0x00000007bfe00000)
 Metaspace       used 3163K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 347K, capacity 388K, committed 512K, reserved 1048576K

unable to create new native thread

线程数量过多

UnableCreateNewThreadDemo.java

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

ulimit -u查看最大一个线程能用线程数

Metaspace

....

省去: cglib代理生产OOM静态内部类的例子。

你可能感兴趣的:(OOM 6)