Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does garbage collection run after OutOfMemoryError is thrown in java?

It would seem as if it should. But could anyone affirm or deny it?

Related are:

Catching java.lang.OutOfMemoryError?

Is it possible to catch out of memory exception in java?

like image 613
Yaneeve Avatar asked Dec 21 '22 13:12

Yaneeve


1 Answers

Does garbage collection run after OutOfMemoryError is thrown in java?

It certainly runs before the OOME is thrown. Indeed, the OOME is typically thrown as a result of the garbage collector finding that it cannot reclaim enough space to satisfy an allocation request1.

Whether it runs after the OOME is thrown depends on what the application does. If the application attempts to continue, the GC will typically run the next time that the application asks for more memory ... in its continued execution.

1 - In fact, it is possible to configure the GC to throw an OOME when it detects that it is spending too much time garbage collection. In this case, the JVM may well have a useful amount of unallocated memory in hand.


Aaron Digulla says this:

So in a carefully designed application, you can catch and handle OOME and the program will survive and continue working.

This is true, but it not something that you should normally do, for two different reasons.

The first reason is that an OOME can be thrown anywhere that a thread attempts to allocate memory. Whatever the JVM was doing at the time will be terminated ... up to the point where the OOME is caught. For instance:

  • If the thread was in the middle of updating a shared data structure (under a lock), then the data structure will be left half-updated.

  • If the thread was due to notify some other thread, then that notification will never happen and the other thread will be stuck waiting.

  • If the thread didn't catch the OOME, then it will exit, and if nothing else notices then you are potentially left with an application that doesn't work anymore.

The problem is that these "breakages" are hard to detect or predict, and hard to recover from.

The second reason is that an OOME is typically indicative of one of the following things:

  • You attempted to perform a computation with insufficient heap memory. If you attempt to recover from the OOME, you are likely to run into the same problem over again.

  • Your application has a memory leak; i.e. some data structure in your application is keeping references to "rubbish" objects, and preventing them from being reclaimed. The chances are that if you attempt to recover from the OOME, nothing will change, and you will run into the same problem again, and again, and again.

So, the preconditions for successful recovery are that:

  • you know that the OOME cannot have damaged anything in the JVM that matters, AND
  • you know that you are not going to run into the OOME again ... because the root cause still exists.

These are HARD preconditions to meet ... in most applications. If they are not met, then there is a good chance that attempting to recover from an OOME will leave it in a worse state than if you have exited and restarted the application.

like image 174
Stephen C Avatar answered May 08 '23 11:05

Stephen C