For white box testing purposes, JVMCi includes API for reflectively calling a compiled nmethod:
jdk.vm.ci.hotspot.HotSpotNmethod.executeVarargs(Object...) [4]
There is currently a race in the implementation of this method whereby between calling this method and executing the instruction at the nmethod's verified entry point (VEP) the code cache sweeper can have unloaded the nmethod.
This API calls an nmethod from a Java call wrapper, but with a special "alternative call target" [1], which is the VEP loaded from the nmethod mirror. The core of the issue is that the VEP is loaded from the nmethod mirror [2] before the transition from VM to Java[3]. This means that before loading the VEP from the nmethod mirror, and getting to the safepoint poll in the transition, the thread could be preempted. It could then happen that the nmethod becomes not entrant, and a sweeper cycle could issue a thread-local nmethod marking handshake. The nmethod has yet to build its frame so is not marked as on-stack. Therefore, before the i2c adapter gets to call this alternative target (the now stale VEP from the nmethod mirror), the nmethod could become zombie. Then the i2c adapter proceeds to call the zombie nmethod. From that point on, insanity follows.
This race has existed since the initial JVMCI implementation. It has not shown up in practice since nmethod sweeping has not been a highly concurrent activity. However, this is changing as of JDK 15 and we are seeing intermittent failures in upstream Graal unit testing.
[1] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.hpp#L91
[2] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.cpp#L431
[3] https://github.com/openjdk/jdk/blob/2d5137e403e16b694800b2ffe18c3640396b757e/src/hotspot/share/runtime/javaCalls.cpp#L70
[4] https://github.com/openjdk/jdk/blob/5ad889b5e0a99863a089ceee215b3f7a7158b78c/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java#L150