What to check when you throw a VirtualMachineError

Even the best code throws errors. Being a developer means knowing how to fix them. In this article, Ram Lakshmanan goes over the many different types of VirtualMachineError for Java, as well as how you can solve these issues and get back to your day without a crashing app.

Java.lang.VirtualMachineError is thrown when a Java virtual machine encounters any internal error or resource limitation which prevents it from functioning. It’s a self-defensive mechanism employed by the JVM to prevent entire application from crashing. In this article, I’ll discuss the many different types of VirtualMachineError, their characteristics, various reasons why they are triggered, and several potentials solutions to fix them.

Types of VirtualMachineError

There are four different types of VirtualMachineError:

OutOfMemoryError StackOverflowError InternalError UnknownError

Let’s review these types in detail in this section.

OutOfMemoryError

Just like the OMG (Oh My God) acronym, OOM (OutOfMemoryError) is quite popular among DevOps community. While most DevOps engineers may think that there is just one OutOfMemoryError, there are actually eight different flavors of OutOfMemoryError:

java.lang.OutOfMemoryError: Java heap space

java.lang.OutOfMemoryError: GC Overhead limit exceeded

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

java.lang.OutOfMemoryError: Permgen space

java.lang.OutOfMemoryError: Metaspace

java.lang.OutOfMemoryError: Unable to create new native thread

java.lang.OutOfMemoryError: Kill process or sacrifice child

java.lang.OutOfMemoryError: reason stack_trace_with_native_method

Each error is triggered by different reasons. Similarly, solutions for these errors differ based on which kind of flavor of OutOfMemoryError issue it is. Here is a beautiful one-page document that summarizes all different kinds of OutOfMemoryError, their causes, and solutions.

In general, OutOfMemoryError can be diagnosed and fixed by analyzing Garbage Collection logs and Heap Dumps. Since analyzing Garbage Collection logs manually can be tedious, you may consider using free tools like GCeasy, HP Jmeter, or IBM GC analyzer. Similarly, you may consider using free tools like HeapHero or Eclipse MAT to analyze heap dumps.

StackOverflowError

A thread’s stack stack stores information about the methods it executes, primitive datatype values, local variables, object pointers, and return values. All of these things consume memory. If a thread’s stack sizes grow beyond the allocated memory limit, then the java.lang.StackOverflowError is thrown. This problem typically happens when a thread recursively invokes same function again and again because of a bug in the executing program. More details on how to debug StackOverflowError and all possible solutions to fix itc an be here.

InternalError

java.lang.InternalError is thrown by JVM for three reasons. If there is a fault in the software implementing the virtual machine, a fault in the underlying host system software, or a fault in the hardware.

However, it’s rare to encounter this kind of InternalError. To understand what specific scenarios may cause InternalError, search for the ‘InternalError’ string in Oracle’s Java Bug database. At the time of writing this article (December 20, 2018), there are only 200 defects reported for this error in Oracle’s Java Bug database. Most of them are fixed. So, don’t worry too much about this one!

UnknownError

java.lang.UnknownError is thrown when an exception or error has occurred, but the Java virtual machine is unable to report the actual exception or error. The UnknownError seldom occurs. In fact, when searching for ‘UnknownError’ in Oracle Java Bug database, there were only 2 defects found reported.

SEE ALSO: Remote debugging for Java applications

Characteristics

VirtualMachineError has couple of primary characteristics:

Unchecked exceptions

Synchronous & asynchronous delivery

Let’s discuss these two characteristics in this section.

Unchecked exceptions

There are two types of Exceptions: checked and unchecked.

Exceptions that are checked at compile time are called Checked Exception. If some methods in your code throw a checked exception, then the method must either handle the exception or it must specify the exception using the ‘throws’ keyword. Examples of the checked exceptions are: IOException, SQLException, DataAccessException, ClassNotFoundException, and more.

Unchecked exceptions do not have this requirement. They don’t have to be caught or declared thrown. All types of VirtualMachineError are unchecked exceptions.

Synchronous & asynchronous delivery

Exceptions can be thrown in two modes: synchronous and asynchronous.

Synchronous exceptions happen at a specific program statement, no matter how many number of times the program has been executed in similar environment. Examples of synchronous exceptions are things like NullPointerException, ArrayIndexOutOfBoundException, etc.

Asynchronous exceptions can happen at any point in time and in any part of program statement. There is no consistency where it can be thrown. All the VirtualMachineErrors are thrown asynchronously, but sometimes they can also be thrown synchronously. StackOverflowError may be thrown synchronously by method invocation, as well as asynchronously due to native method execution or Java Virtual Machine resource limitations. Similarly, OutOfMemoryError may be thrown synchronously during object creation, array creation, class initialization, and boxing conversion, as well as asynchronously.