JDK-8367902 : Allocation after Universe::before_exit() in the VM shutdown sequence
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 7
  • Priority: P2
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2025-09-17
  • Updated: 2025-10-31
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 26
26Unresolved
Related Reports
Relates :  
Description
Currently, we call `Universe::before_exit()` before invoking `JvmtiExport::post_thread_end`. The `before_exit()` signals to the GCs that a shutdown has started. However, the subsequent call to `JvmtiExport::post_thread_end` may still execute code that requires memory allocation or may trigger GC activity. This limits how the GCs can react to the shutdown signal called in `before_exit()`.

Investigate moving the `Universe::before_exit()` call after `JvmtiExport::post_thread_end()`. Reordering would ensure that any allocations or GC activity caused during `post_thread_end()` occur under normal GC conditions, and only after that point would the GCs be signaled that shutdown is in progress.
Comments
I've been running tier1-7 without problem with stack of patches: 1) Move the JVMTI code to before the GC exits: https://github.com/openjdk/jdk/compare/master...stefank:jdk:8367902_before_exit_and_jvmti 2) Reverted the the 2 second sleep workaround that was put in place because JVMTI could allocate after the GC has exited. The idea is to let Java threads block if they try to trigger a GC after the GC has exited: https://github.com/openjdk/jdk/compare/master...stefank:jdk:remove_2s_shutdown_workaround 3) Remove the highly dubious code that sleeps in the hope to solve some races: https://github.com/stefank/jdk/compare/remove_2s_shutdown_workaround...stefank:jdk:remove_wait_for_threads_in_native_to_block
31-10-2025

Thanks for pointing out that I confused the two OnUnload callbacks.
29-10-2025

You linked to the JNI OnUnload spec not the JVMTI one: https://docs.oracle.com/en/java/javase/25/docs/specs/jvmti.html#onunload JVM TI does not have any such language warning about what the function can do unfortunately, though it is supposed to be a cleanup function for the agent. So for consistency I would move JvmtiAgentList::unload_agents as well.
29-10-2025

OK. Thanks for clarifying. Yes, moving those would be needed. What about the Agent_OnUnload callback? The documentation says: https://docs.oracle.com/en/java/javase/25/docs/specs/jni/invocation.html ``` This function can be used to perform cleanup operations. Because this function is called in an unknown context (such as from a finalizer), the programmer should be conservative on using Java VM services, and refrain from arbitrary Java call-backs. ``` It sort-of says that the the library shouldn't call Java code, but it doesn't outright forbid it. I'm not sure how to interpret this piece.
28-10-2025

> Are you saying this as a reason to not fix this bug? No I'm just saying that shutdown is complex, and changing things can have unexpected affects. Looking at the code I would think you would want to move post_thread_end and post_vm_death to before Universe::before_exit to avoid the allocation issue.
28-10-2025

My comment on this in Leonid's VM_DEATH PR: https://github.com/openjdk/jdk/pull/27504#issuecomment-3345735398 Serguei's ACK: https://github.com/openjdk/jdk/pull/27504#issuecomment-3354166387
28-10-2025

Moving to JVMTI because code should not expect to be able to allocate *after* we have shut down the GC.
28-10-2025

I'm bumping this to P2 because I really want to solve this so that we can remove the ugly hack that was added to quickly workaround this issue.
28-10-2025

> As discussed in JDK-8366865 there are numerous potential "bad" interactions once shutdown commences, and before we hit the termination safepoint. Are you saying this as a reason to not fix this bug?
28-10-2025

> It is not only the `JvmtiExport::post_thread_end` problem. The daemon threads are still executing and they might require memory allocation. But those are not the problem . The problem that I want to get fixed is that we don't perform allocation from the thread that is performing the shutdown. The reason why that thread is important is that if we allocate while shutting down we will / can deadlock. This doesn't happen with other Java threads (daemon or not).
28-10-2025

As discussed in JDK-8366865 there are numerous potential "bad" interactions once shutdown commences, and before we hit the termination safepoint.
28-10-2025

It is not only the `JvmtiExport::post_thread_end` problem. The daemon threads are still executing and they might require memory allocation.
27-10-2025