Skip to content

Fix jdk.jfr module resolution for JFR V2 startup and jcmd - #24714

Merged
tajila merged 1 commit into
eclipse-openj9:masterfrom
tomal-majumder:fix-jfr-TestModularImage-test
Sep 12, 2026
Merged

tajila merged 1 commit into
eclipse-openj9:masterfrom
tomal-majumder:fix-jfr-TestModularImage-test

Conversation

@tomal-majumder

Copy link
Copy Markdown
Contributor

JFR V2 (gated behind -XX:+EnableOpenJ9ExperimentalFlightRecording
on JDK17) assumed jdk.jfr was always resolved before touching any
of its classes. That breaks for a --module launch whose module
declares no "requires jdk.jfr", and for a jcmd JFR.start with no
-XX:StartFlightRecording on the command line. Both exercised by
test/jdk/jdk/jfr/jvm/TestModularImage.java, which failed several
ways: the "Started recording" print was silently dropped, a native
assertion crashed the VM when jdk.jfr was not resolved already
(e.g. --add-mods jdk.jfr not given at launch), and a module-resolution
failure printed the wrong text.

This introduces the following changes:

  • Default LogTag.JFR_START to INFO instead of WARN, and tag the
    startup banner with it (was tagged as plain LogTag.JFR), so it
    is no longer filtered by the default logging threshold.

  • Inject jdk.jfr into the root module set at boot when
    -XX:StartFlightRecording is given with JFR V2 enabled, via a
    synthesized jdk.module.addmods.<n> property. Extracted the
    shared injection logic into one addRequiredModuleProperty()
    helper, reused by two other existing call sites.

  • Add ensureJfrModuleAvailable(): for jcmd with no
    -XX:StartFlightRecording on the command line, checks the boot
    layer, then loads jdk.jfr on demand since nothing requested it
    at startup. JFR internal structures now only initialize on
    success, removing a native assertion crash. jcmd DCmd entry
    points check this and return a clean error instead of failing
    in reflection.

  • Print a leading error line in ClassLoader.java's module
    bootstrap catch block, matching the boot-layer error text
    TestModularImage.java expects.

Fixes: #23708

Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java Outdated
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java Outdated
Comment thread runtime/jcl/common/jclcinit.c
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java Outdated
Comment thread runtime/jcl/common/jdk_jfr_internal_JVM_common.cpp Outdated
Comment thread runtime/jcl/common/jdk_jfr_internal_JVM_common.cpp Outdated
@JasonFengJ9

Copy link
Copy Markdown
Member

which failed several
ways: the "Started recording" print was silently dropped, a native
assertion crashed the VM when jdk.jfr was not resolved already
(e.g. --add-mods jdk.jfr not given at launch), and a module-resolution
failure printed the wrong text.

Can you provide more details about the failure or the assertion, or is there any issue reference?

jcmd send/receive AttachAPI commands to a target process which has to run with -XX:+EnableOpenJ9ExperimentalFlightRecording to enable JFR V2 support.
However there is no need for jcmd to do actual JFR operations, if so, the dependence should be removed.

@tomal-majumder
tomal-majumder force-pushed the fix-jfr-TestModularImage-test branch from 2d0489d to 28b8acd Compare September 10, 2026 03:02
Comment thread runtime/vm/jfr.cpp
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java Outdated
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java
@tomal-majumder
tomal-majumder force-pushed the fix-jfr-TestModularImage-test branch from 28b8acd to 35f6509 Compare September 10, 2026 18:16
@tomal-majumder

Copy link
Copy Markdown
Contributor Author

which failed several
ways: the "Started recording" print was silently dropped, a native
assertion crashed the VM when jdk.jfr was not resolved already
(e.g. --add-mods jdk.jfr not given at launch), and a module-resolution
failure printed the wrong text.

Can you provide more details about the failure or the assertion, or is there any issue reference?

jcmd send/receive AttachAPI commands to a target process which has to run with -XX:+EnableOpenJ9ExperimentalFlightRecording to enable JFR V2 support. However there is no need for jcmd to do actual JFR operations, if so, the dependence should be removed.

On the assertion / failure details:
The crash is in jfrInitializeInternalStructures() (runtime/vm/jfr.cpp). No separate tracking issue for this one. This PR covers it.

TestModularImage builds a jlinked image containing hello.world + jdk.jfr (Calls it with-jfr) and launches it with --module hello.world/hello.Main. hello.world's module-info has no requires jdk.jfr. The main issue is: a --module hello.world/hello.Main launch takes only the named module plus what it requires as the root set. jdk.jfr is pulled in only if some root requires it or --add-modules jdk.jfr is passed. Neither applies here, so even if jdk.jfr is in the image but never gets resolved into the boot layer.

So, with -XX:+EnableOpenJ9ExperimentalFlightRecording -XX:StartFlightRecording flags on, JFR V2 startup triggers JFRHelpers's static initializer, which (V2 enabled) calls VM.initializeInternalJFRStructures() → jfrInitializeInternalStructures() in runtime/vm/jfr.cpp:

...
jfrEventClass = internalFindClassUTF8(currentThread, "**jdk/jfr/Event**", ..., vm->systemClassLoader, 0);
Assert_VM_notNull(jfrEventClass);   --> **crashes here** 
...

jdk/jfr/Event lives in jdk.jfr, so internalFindClassUTF8(..., systemClassLoader, 0) returns NULL, Assert_VM_notNull aborts the VM in JFRHelpers's during bootstrap; before main runs. So hello, world never prints, and the Started recording banner never gets a chance either. That is why the jdk.jfr is injected to root module set in the boot time using jdk.module.addmods.<n> property when both EnableOpenJ9ExperimentalFlightRecording and StartFlightRecording flags are provided.

On jcmd and the JFR dependency:
Agreed the jcmd tool has no JFR dependency; it's pure AttachAPI. The dependency is in the target: JFR.start/stop/dump/configure invoke jdk.jfr.internal.dcmd.DCmd*, which live in jdk.jfr. -XX:+EnableOpenJ9ExperimentalFlightRecording turns on V2 support but does not pull jdk.jfr into the module graph. So for "flag set, no -XX:StartFlightRecording, JFR.start via jcmd later", jdk.jfr isn't resolved during boot time and has to be brought in on demand. That's what ensureJfrModuleAvailable() in JFRHelpers.java does. If it can't be resolved (e.g. a jlinked image without the module), the DCmd path now reports "Flight Recorder can not be enabled." and does no JFR work, so there's no hard dependency in that case.

@JasonFengJ9

Copy link
Copy Markdown
Member

Neither applies here, so even if jdk.jfr is in the image but never gets resolved into the boot layer.

Thanks the detailed analysis @tomal-majumder

jdk.jfr is part of boot modules, it seems jlink image bootup differently and jdk.jfr wasn't resolved unless loading explicitly.

Agreed the jcmd tool has no JFR dependency; it's pure AttachAPI.

In this case, please update the commit message to remove jcmd reference related to JFR operation and jdk.jfr module resolution issue.

Comment thread jcl/src/java.base/share/classes/java/lang/ClassLoader.java
Comment thread jcl/src/java.base/share/classes/java/lang/JFRHelpers.java Outdated
Comment thread runtime/vm/jfr.cpp
@tomal-majumder
tomal-majumder force-pushed the fix-jfr-TestModularImage-test branch from 35f6509 to 676180c Compare September 11, 2026 06:11
@tomal-majumder

Copy link
Copy Markdown
Contributor Author

Neither applies here, so even if jdk.jfr is in the image but never gets resolved into the boot layer.

Thanks the detailed analysis @tomal-majumder

jdk.jfr is part of boot modules, it seems jlink image bootup differently and jdk.jfr wasn't resolved unless loading explicitly.

Agreed the jcmd tool has no JFR dependency; it's pure AttachAPI.

In this case, please update the commit message to remove jcmd reference related to JFR operation and jdk.jfr module resolution issue.

Thanks for the suggestion! Commit message updated!

@tomal-majumder
tomal-majumder force-pushed the fix-jfr-TestModularImage-test branch from 676180c to f8ec99e Compare September 11, 2026 15:41
Comment thread runtime/vm/jfr.cpp
JFR V2 (gated behind -XX:+EnableOpenJ9ExperimentalFlightRecording
on JDK17) assumed jdk.jfr was always resolved before touching any
of its classes. That breaks for a --module launch whose module
declares no "requires jdk.jfr", and for a JFR diagnostic command
(JFR.start/stop/dump via jcmd) executed after boot with no
-XX:StartFlightRecording on the original command line. Both
exercised by test/jdk/jdk/jfr/jvm/TestModularImage.java, which
failed several ways: the "Started recording" print was silently
dropped, a native assertion crashed the VM when jdk.jfr was not
resolved already (e.g. --add-mods jdk.jfr not given at launch),
and a module-resolution failure printed the wrong text.

This introduces the following changes:

- Default LogTag.JFR_START to INFO instead of WARN, and tag the
  startup banner with it (was tagged as plain LogTag.JFR), so it
  is no longer filtered by the default logging threshold.

- Inject jdk.jfr into the root module set at boot when
  -XX:StartFlightRecording is given with JFR V2 enabled, via a
  synthesized jdk.module.addmods.<n> property. Extracted the
  shared injection logic into one addRequiredModuleProperty()
  helper, reused by two other existing call sites.

- Add ensureJfrModuleAvailable(): when a JFR diagnostic command
  needs jdk.jfr, but nothing requested it at startup, checks the
  boot layer, then loads jdk.jfr on demand. JFR internal
  structures now only initialize on success, removing a native
  assertion crash. The diagnostic command entry points check this
  and return a clean error instead of failing in reflection.

- Print a leading error line in ClassLoader.java's module
  bootstrap catch block, matching the boot-layer error text
  TestModularImage.java expects.

Signed-off-by: Tomal Majumder <tomal.majumder@ibm.com>
@tomal-majumder
tomal-majumder force-pushed the fix-jfr-TestModularImage-test branch from f8ec99e to 7529ccb Compare September 11, 2026 16:37
@tajila

tajila commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

jenkins test sanity,extended.functional alinux64 jdk17,jdk21

@tajila

tajila commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

jenkins compile win jdk11,jdk17

@tajila

tajila commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

jenkins test sanity aix jdk17

@tajila
tajila merged commit e801cec into eclipse-openj9:master Sep 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JFR Test Failure: TestModularImage

4 participants