29 Ocak 2019 Salı

OutOfMemoryError Sınıfı - OOM

Giriş
Kalıtım şeklen şöyle
Serializable Throwable Error VirtualMachineError OutOfMemoryError
Bu exception'ın fırlatılmasının bir sürü sebebi olabilir. Hata mesajlarından bazıları şöyle
1.java.lang.OutOfMemoryError: Java heap space
2.java.lang.OutOfMemoryError: GC Overhead limit exceeded
3.java.lang.OutOfMemoryError: Requested array size exceeds VM limit
4.java.lang.OutOfMemoryError: Permgen space
5.java.lang.OutOfMemoryError: Metaspace.
6.java.lang.OutOfMemoryError: Unable to create new native thread
7.java.lang.OutOfMemoryError: Kill process or sacrifice child
8.java.lang.OutOfMemoryError: reason stack_trace_with_native_method
9. java.lang.OutOfMemoryError: Direct buffer memory

Metaspace yazısına bakabilirsiniz.

Şeklen şöyle

1. Java heap space
Örnek
Şöyle yaparız
//JVM parameter:-Xmx12m
public class JavaHeapSpaceDemo {
  static final int SIZE = 2 * 1024 * 1024;
  public static void main(String[] a) {
    int[] i = new int[SIZE];
  }
}
//Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
2. GC overhead limit exceeded
Açıklaması şöyle
... when the Java process spends more than 98% of the time executing GC, only less than 2% of the memory is recovered, and If this action is repeated 5 times in a row, java.lang.OutOfMemoryError:GC overhead limit exceededan error ( commonly known as: garbage collection ). Simply put, the application has basically exhausted all available memory and the GC cannot reclaim it.
Örnek
Şöyle yaparız
//JVM parameter: -Xmx14m -XX:+PrintGCDetails public class KeylessEntry { static class Key { ... } public static void main(String[] args) { Map m = new HashMap(); while (true){ for (int i = 0; i < 1000; i++){ if (!m.containsKey(new Key(i))){ m.put(new Key(i), "Number:" + i); } } System.out.println("m.size()=" + m.size()); } } }
Çıktı şöyle. Burada heap bitmeden önce GC çok fazla çalıştığı için OOM alınıyor.
... m.size()=54000 m.size()=55000 m.size()=56000 Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
3. Requested array size exceeds VM limit
Şöyle yaparız.
public static void main(String[] args) { int[] arr = new int[Integer.MAX_VALUE]; } Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
6. Unable to create new native thread
Şöyle yaparız.
public static void main(String[] args) { while(true){ new Thread(() -> { try { Thread.sleep(Integer.MAX_VALUE); } catch(InterruptedException e) { } }).start(); } } Error occurred during initialization of VM java.lang.OutOfMemoryError: unable to create new native thread
9. Direct buffer memory
Şöyle yaparızDirect buffer memory nesne ile işimiz bitse dahil nesne GC ile silindiğinde geri bırakılır. Dolayısıyla native alan GC'den önce bitebilir.
//VM Options:-Xms10m,-Xmx10m,-XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m public class DirectBufferMemoryDemo { public static void main(String[] args) { System.out.println("maxDirectMemory is:" + sun.misc.VM.maxDirectMemory() / 1024 / 1024 + "MB"); //ByteBuffer buffer = ByteBuffer.allocate(6*1024*1024); ByteBuffer buffer = ByteBuffer.allocateDirect(6*1024*1024); } } //Output maxDirectMemory is:5MB Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
Çözümler şöyle
1. Java can only use Direct ByteBuffer through the ByteBuffer.allocateDirect method , so you can intercept this method for troubleshooting through online diagnostic tools such as Arthas

2. Check if NIO is used directly or indirectly, such as netty, jetty, etc.

3. -XX:MaxDirectMemorySizeAdjust the upper limit of Direct ByteBuffer through startup parameters

4. Check if the JVM parameter has an -XX:+DisableExplicitGCoption , if so, remove it, because this parameter will invalidate the System.gc()

5. Check the off-heap memory usage code to confirm whether there is a memory leak; sun.misc.Cleaneror clean() actively release the memory space held by Direct ByteBuffer through the method called by reflection

6. The memory capacity is really insufficient, upgrade the configuration

Hiç yorum yok:

Yorum Gönder