2

Bad practices aside...

We implement a Java Thread Runnable and in its run() have a while(true) do some stuff. First thing inside the while is a try/catch/finally saying, if anything is caught, sleep and then "exit" (which would continue the while).

If there was an OutOfMemory issue outside the thread at a higher level, would the thread just die altogether? If so, the try/catch/finally wouldn't catch because the execution of the OOM is outside that scope?

Would the thread be garbage collected or not (it died ungracefully).

TLDR: If a Runnable gets OutOfMemory does it die and just stop in its tracks, or is that exception thrown within the scope of the execution?

run(){
  while(true){
    try {
      stuff
    } catch{  //blah
    } finally{sleep}
  }
}
Walls
  • 3,972
  • 6
  • 37
  • 52
  • Are you talking about `OutOfMemory` thrown inside the `try` block or from a different thread? – tsolakp Feb 01 '18 at 21:02
  • @tsolakp looks like thrown out of it in a hibernate thread. `WARN org.hibernate.engine.loading.internal.CollectionLoadContext:389 - HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [10] entries Exception in thread "http-bio-8080-exec-25" java.lang.OutOfMemoryError: GC overhead limit exceeded`. Shortly after, I realized the `while` wasn't firing off. – Walls Feb 01 '18 at 21:07

4 Answers4

3

An OutOfMemoryError is thrown when an allocation fails. Therefore, it is passed up the call chain of the thread which made the allocation attempt. Only try … catch blocks encapsulating this invocation chain, resp. the allocation itself may catch it.

There is no direct effect on the JVM’s overall operation nor other threads. Of course, if the reason for throwing an OutOfMemoryError is that the JVM is low on memory, there’s a chance that this extraordinary condition itself affects the overall JVM operation or other threads at the same time. E.g., all threads attempting an allocation at that time may fail with an error.

As demonstrated by this answer, multiple threads may encounter the same OutOfMemoryError instance if the memory is so low that no individual error instances can be constructed. But this does not mean that thrown errors may slosh over to different threads. There’s still a causal relationship between a failed allocation in a thread and the error being caught within that thread. Or con­cur­ren­cy frameworks may hand over the error instance to an initiating thread if an asynchronous op­era­tion failed.

The only reason for a JVM to automatically exit on an OutOfMemoryError is an indirect one; if all non-daemon threads exited in response to an OutOfMemoryError, e.g. when not catching it at all, the JVM will exit because that’s the standard behavior when no non-daemon thread is alive.

There are scenarios where an application could recover from a single failed allocation when the JVM is not low on memory in general, e.g. if the failed allocation was extraordinary large (the expression new long[Integer.MAX_VALUE-8] requires ~16GiB), if it hits general limitations (new long[Integer.MAX_VALUE] is not supported by HotSpot, even if there’s enough memory), or need special memory rather than ordinary heap space (native buffers, graphics memory or PermGen space in older JVMs).

Holger
  • 285,553
  • 42
  • 434
  • 765
2

When an Error not an Exception ocurs the whole JVM -> all Threads will die in most cases.
If your background thread doesn't uses shared resurces it MAYBE surives but as said its very uncommon. Ah and if it is an deamon threas it will die instat.
What do you mean with the try catch final? You cannot realy catch an error, it is like a bullet:

an error is catchable, you can try to catch but if its thrown you die.

Niton
  • 189
  • 4
  • 16
1

Homework time again?

An OutOfMemoryError is an error, not an exception. You could catch an Error -after all, they derive from Throwable, as does Exception- but it's not a very good idea.

Your thread doesn't die, your entire JVM does. Because there's really no graceful way to recover from an OutOfMemoryError.

SeverityOne
  • 2,476
  • 12
  • 25
  • 1
    It is not necessary for JVM to die on `OutOfMemoryError`. – tsolakp Feb 01 '18 at 20:46
  • Not homework time... debugging production time... *shudder*, hence the "bad practices aside". Was more for my curiosity. – Walls Feb 01 '18 at 20:46
  • It's not production code either. What you've written is pseudo-Java that'll never compile. – SeverityOne Feb 01 '18 at 20:53
  • Because I'm going to obfuscate prod code when making an example and keeping it simple to just the relevant information to the question. – Walls Feb 01 '18 at 21:01
  • As an interesting counter-poiint, Akka intentionally catches Throwables, including out of memory, to effect a graceful shutdown. In most instances this is possible. – Sam Feb 01 '18 at 21:19
  • Can the JVM reover: https://stackoverflow.com/questions/3058198/can-the-jvm-recover-from-an-outofmemoryerror-without-a-restart – Gonen I Feb 04 '18 at 17:07
1

When you catch OutOfMemoryError in your while loop everything you allocated(assuming they are only referenced in your loop) up to the point memory error, will be eligible to garbage collection.(this will also be the case without the error)

If a thread dies because of OutOfMemoryError, its stack will be destroyed and all the object that are referenced from only that stack will also be eligible to garbage collection.

Even if main thread dies because of OutOfMemoryError if you have non-daemon threads alive, the jvm will not die.

OutOfMemoryError can have different causes, they are listed here https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html

Normally It is advised to clean up and exit when you catch OutOfMemoryError.

miskender
  • 7,460
  • 1
  • 19
  • 23