4

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?

Community
  • 1
  • 1
Yaneeve
  • 4,751
  • 10
  • 49
  • 87
  • I hope the JVM tries to run the garbage collection before throwing the OOME... – poussma Nov 22 '12 at 08:47
  • @ZNK-M look at http://stackoverflow.com/questions/12298725/is-the-garbage-collector-guaranteed-to-run-before-out-of-memory-error – Yaneeve Nov 22 '12 at 08:48
  • @Yaneeve If you've seen that question and its answer already, what is your question? Whether the JVM tries the same thing it did before the error was thrown again to see if the result is different? – arne.b Nov 22 '12 at 08:55
  • @arne.b yes, that is if I release any strongly reachable object, will it now be garbage collected (or an attempt would be made) – Yaneeve Nov 22 '12 at 08:57
  • @SeanOwen Yes I realy do mean after – Yaneeve Nov 22 '12 at 09:00

4 Answers4

5

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
4

Yes. GC runs right before the OutOfMemoryError and it continues to work.

OOME is an error like any other: It means the runtime might be in a problematic state but that doesn't stop Java. So when you catch the error, you can delete some references and the error will go away.

The problem is of course that you can't know whether other code (for example in another thread) might need memory while you try to find references to cut and that code could throw another OOME and break fatally.

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

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Sorry Aaron, @StephenC's answer is even more detailed than yours, but yours is a good and solid answer just the same – Yaneeve Nov 22 '12 at 09:45
2

If your question is really whether it runs after OutOfMemoryError: yes. It also runs before. OutOfMemoryError does not terminate the JVM; it's thrown instead of the object allocation succeeding and the program continues. The JVM continues, including garbage collection.

In fact, some frameworks like Tomcat design for this. They allocate a bit of memory that is not used, and in case of OutOfMemoryError, release it, in order to have enough room to complete and orderly shutdown. This requires that the GC continue to run.

Sean Owen
  • 66,182
  • 23
  • 141
  • 173
  • It was a real hard choice to decide which answer to choose, yours or @AaronDigulla's. His was a bit more explicit. I did love your Tomcat example though! – Yaneeve Nov 22 '12 at 09:13
0

In the javadoc of the OOME, it says:

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

That means it has been run before the Error.

BTW, when you get such error, it is very hard to recover because you are not guarantee to have enough memory to do anything else. If you used the last bytes of memories you are stuck. If you had this error because you tried to allocate 4Gb in one shot then you still have a chance to save your soul, but if you need those 4Gb to proceed, then you are stuck again.

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/OutOfMemoryError.html

poussma
  • 7,033
  • 3
  • 43
  • 68