When an nmethod is deoptimized, its scalar-replaced objects are reallocated on the heap. When this reallocation fails due to lack of memory, an OOME is raised, and the nmethod's corresponding interpreter frames are popped, and their held locks are released, but *without* running their exception handlers. Because we allow recovery from OOME, execution may resume in some caller, in apparent violation of ยง14.20 of the JLS.
This behavior was introduced by JDK-6898462.
A possible solution might be to pop *all* frames in the thread and to trigger the thread's uncaught exception handler with the OOME. A mechanism for freeing native resources might be needed as well.
Another possible solution is to ensure this situation never arises by reserving heap space in some emergency region that would ensure, on nmethod-entry, that there will be enough heap memory in the case of reallocation.