Instance resolves OutOfMemoryError issues with Java exceptions

  • 2021-06-28 12:37:30
  • OfStack

In the description of the Java Virtual Machine Specification, there is a possibility that OOM exceptions will occur in several run areas of virtual machine memory in addition to program counters.Here, you validate the contents stored in each run-time zone with code and discuss how to handle them.

Java heap overflow

The Java heap is used to store object instances, and memory overflow exceptions occur when the number of objects reaches the maximum heap capacity limit as long as objects are continuously created and accessible paths between GC Roots and objects are guaranteed to avoid being cleared by the garbage collection mechanism.

Anomaly reproduction

The code takes the following virtual machine parameters:


-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

This limits the size of the Java heap to 20 MB and is not expandable.The parameter -XX:+HeapDumpOnOutOfMemoryError allows Dump to overflow the current memory heap dump snapshot in case of a memory overflow exception on the virtual machine for timely analysis.

Verify with the following code:


public class HeapOOM {

  static class OOMObject {

  }

  public static void main(String[] args) {

    List<OOMObject> list = new ArrayList<OOMObject>();

 

    while (true) {

      list.add(new OOMObject());

    }

  }

}

Run result:


java.lang.OutOfMemoryError: Java heap space

Dumping heap to java_pid3460.hprof ...

Heap dump file created [28199779 bytes in 0.237 secs]

Resolvent

The OOM exception of Java heap memory is a common memory overflow exception in practical applications, which is often followed by the prompt "Java heap space".

To resolve the anomalies in this area, a general method is to first use memory image analysis tools, such as MAT, to confirm whether a memory leak or a memory overflow has occurred.

If it is a memory leak, you can take a step through the tool to look at the reference chain from the leaked object to GC Roots and find out how the leaked object is related to GC Roots and causes the garbage collector to not automatically reclaim their space.

If it is not a memory leak, in other words, objects in memory do need to survive, then the heap parameters of the virtual machine should be checked to see if they can be increased compared to the physical memory of the machine.At the code level, there are instances where objects have a long life cycle and hold state for too long, attempting to reduce memory consumption while the program is running.

Virtual Machine Stack and Local Method Stack Overflow

Because virtual machine stacks or local method stacks are not distinguished in the HotSpot virtual machine, the -Xoss parameter is invalid for HotSpot, and the stack capacity is only set by the -Xss parameter.

Anomaly reproduction

Under a single thread, the code takes the following virtual machine parameters:


-Xss128k

Use this parameter to reduce the stack capacity and reproduce the exception using the following code:


public class JavaVMStackSOF {

 

  private int stackLength = 1;

 

  public void stackLeak() {

    stackLength++;

    stackLeak();

  }

 

  public static void main(String[] args) throws Throwable {

    JavaVMStackSOF oom = new JavaVMStackSOF();

    try {

      oom.stackLeak();

    } catch (Throwable e) {

      System.out.println("stack length:" + oom.stackLength);

      throw e;

    }

  }

}

Resolvent

If you use the virtual machine default parameters, the stack depth is perfectly fine in most cases (since the frame size each method pushes into the stack is not the same, so in most cases it is only possible to reach 1000-2000), which should be sufficient for normal method calls, including recursion.

However, if memory overflow is caused by too many threads, more threads can only be exchanged by reducing the maximum stack and reducing the stack capacity without reducing the number of threads or replacing 64-bit virtual machines.

Native direct memory overflow

DirectMemory capacity can be specified by -XX:MaxDirectMemorySize, or defaults to Java maximum heap 1 if not specified.

Anomaly reproduction

Use the following virtual machine parameters:


-Xmx20M -XX:MaxDirectMemorySize=10M

Reproduce the exception using the following code:


public class DirectMemoryOOM {

  private static final int _1MB = 1024 * 1024;

  public static void main(String[] args) throws Exception {

    Field unsafeField = Unsafe.class.getDeclaredFields()[0];

    unsafeField.setAccessible(true);

    Unsafe unsafe = (Unsafe) unsafeField.get(null);

    while (true) {

      unsafe.allocateMemory(_1MB);// Direct request for memory allocation 

    }

  }

}

Resolvent

An obvious feature of memory overflow caused by DirectMemory is that no obvious exception is seen in the Heap Dump file.

If you find that the Dump file after OOM is very small and NIO is used directly or indirectly in the program, then you can consider checking whether 1 is the cause of this.

That's all we've sorted out. Thank you for your support for this site.


Related articles: