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 concurrency frameworks may hand over the error instance to an initiating thread if an asynchronous operation 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).