The i2c adapter sets a thread-local "callee_target" Method*, which is caught (and cleared) by SharedRuntime::handle_wrong_method if the i2c call is "bad" (e.g. not_entrant). This error handler forwards execution to the callee c2i entry. If the SharedRuntime::handle_wrong_method method is called again due to the i2c2i call being still bad, then we will crash the VM in the following guarantee in SharedRuntime::handle_wrong_method:
Method* callee = thread->callee_target();
guarantee(callee != NULL && callee->is_method(), "bad handshake");
Unfortunately, the c2i entry can indeed fail again if it, e.g., hits the new class initialization entry barrier.
I think a solution to this problem should stop making assumptions about how many things can go wrong when calling a method from the interpreter.
I caught this in ZGC where the timing window for hitting this issue seems to be wider due to concurrent code cache unloading. But it is equally problematic for all GCs.