JDK-8212159 : assert(zombie_ok || !nm->is_zombie()) failed: cannot lock a zombie method
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 8,11,12
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2018-10-13
  • Updated: 2020-11-20
  • Resolved: 2019-11-20
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 14
14Resolved
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
JVMTI agent that calls GenerateEvents(JVMTI_EVENT_COMPILED_METHOD_LOAD) may crash JVM with the following error:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (c:/Users/Andrei/java/jdk/src/hotspot/share/code/nmethod.cpp:2038), pid=13040, tid=16060
#  assert(zombie_ok || !nm->is_zombie()) failed: cannot lock a zombie method
#
# JRE version: OpenJDK Runtime Environment (11.0+28) (slowdebug build 11+28)
# Java VM: OpenJDK 64-Bit Server VM (slowdebug 12-internal+0-adhoc.Andrei.jdk, compiled mode, tiered, compressed oops, g1 gc, windows-amd64)
# Core dump will be written. Default location: C:\Users\Andrei\java\jvmti-race\hs_err_pid13040.mdmp
#

The reproducer agent is attached. Run
java -agentpath:jvmtiCompiledZombie.dll -Xcomp -XX:ReservedCodeCacheSize=20m -jar SwingSet2.jar

The crash sometimes happens even without -Xcomp and ReservedCodeCacheSize, but these flags help to reproduce the issue frequently.

The problematic code is in JvmtiCodeBlobEvents::generate_compiled_method_load_events() function:

  while(iter.next_alive()) {
    nmethod* current = iter.method();
    // Lock the nmethod so it can't be freed
    nmethodLocker nml(current);

Here is a race condition. A method can become zombie between next_alive() check and nmethodLocker::lock_nmethod() which asserts that the method being locked is not zombie.

The trivial fix would be to allow locking zombies here.

The same crash was also seen on JDK 8 with the following stack trace:
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xac703a]  VMError::report_and_die()+0x2ba
V  [libjvm.so+0x4fbf72]  report_vm_error(char const*, int, char const*, char const*)+0x62
V  [libjvm.so+0x8e6f71]  nmethodLocker::lock_nmethod(nmethod*, bool)+0x61
V  [libjvm.so+0x736e82]  JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv*)+0x92
V  [libjvm.so+0x74d8ab]  jvmti_GenerateEvents+0x1fb
C  [libasyncProfiler.so+0xb5a0]  VM::attach(JavaVM_*)+0x60

Since JDK 8 has `guarantee` instead of `assert` here, release builds are also affected.
Comments
This is just an alternative timing of JDK-8212160. Thank you for the test case!
20-11-2019

This bug seems to be a dup of the JDK-8173361. Will check it with Coleen.
19-11-2019

This is pretty interesting. There seems to be a hole in the synchronization for COMPILED_METHOD_LOAD events. Will try to investigate it when there is a chance.
29-10-2019