On Fri, 1 May 2026 15:37:12 GMT, Kevin Walls <[email protected]> wrote:
> This implements "jcmd on core files" for Linux, and for MiniDumps on Windows > (MacOS is "future work"). > jcmd "revives" the VM memory and .so/.dll from the core/minidump, and runs > the existing native diagnostic command parser and command implementations. > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). Summary: ----- Revive memory from a core file, and load the JVM library, to create a duplicate of what was in memory when the core was created. This will likely conflict with the running jcmd JVM process, so it is done in a new helper process. The helper calls a new method in the JVM to reset some VM state, then jumps to the existing jcmd (diagnostic command) parser. The native diagnostic commands run almost as if nothing has happened. A few places in the VM check if we are revived. The test test/hotspot/jtreg/serviceability/revival/JCmdRevival.java crashes in a few different ways, and runs the jcmds on the core/minidump ( make images test TEST=test/hotspot/jtreg/serviceability/revival ). Tests could in time be more integrated with other jcmd testing, but for now this separate test is less disruptive. More detail: ----- jcmd: src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java Uses attach API, and on a core file we call into: src/jdk.attach/share/classes/sun/tools/attach/VirtualMachineCoreDumpImpl.java This launches the "revivalhelper" process: src/jdk.attach/share/native/revivalhelper/revivalhelper.cpp ...which calls revive_image() and revival_dcmd() defined in src/jdk.attach/share/native/revivalhelper/revival.cpp revive_image() does some pre-work: The JVM .so/.dll needs to be relocated (rebased) to load at the same address as that in the core file. Linux does that relocation in elffile.cpp, on Windows it uses a Windows API (see pefile.cpp). Relocation means changing the actual file, so a copy is made. A directory core.revival is created for this copy, and serves as a cache to hold a few other files to speed up subsequent runs. One file lists the memory mappings from the dump that will be mapped into the helper process. Another file lists a few symbols. That cache creation/analysis phase is somewhat separate to give some flexibility: if the analysis required more memory usage or libraries to load that cause more memory conflicts, it could be run in a separate process. This does not appear necessary at the moment on these platforms. There are platform-dependent native implementation parts in src/jdk.attach/linux/native/revivalhelper/revival_linux.cpp and src/jdk.attach/windows/native/revivalhelper/revival_windows.cpp Mapping memory in revivalhelper can fail due to a conflict. This is not generally very common, but the helper will exit and jcmd will retry. Address space layout randomization both causes and fixes these clashes. revivalhelper cooperates with the VM - you need to crash a VM with this change to use jcmd on a core file. The cooperation in the VM is in the Thread::process_revival() method (open/src/hotspot/share/runtime/thread.cpp) wich resets some VM state and returns the one structure shared between VM and revivalhelper. The core's JVM and that found for revival must be exactly the same. Locally this is automatic, but if core is transported or the JVM at the path in the core has changed, run e.g. "jcmd -L /my/path core help" where you have either a JDK or just libjvm.so in /my/path (there is a version check also, based on finding string pointers to JVM version info which should be readable from both the binary and the core file). ------------- PR Comment: https://git.openjdk.org/jdk/pull/31011#issuecomment-4360664113
