JDK-8227011 : Starting a JFR recording in response to JVMTI VMInit and / or Java agent premain corrupts memory
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jfr
  • Affected Version: 11,12,13
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2019-07-01
  • Updated: 2022-01-05
  • Resolved: 2019-07-02
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 11 JDK 13 JDK 14 Other
11.0.5Fixed 13 b28Fixed 14Fixed openjdk8u262Fixed
Related Reports
Relates :  
Relates :  
Description
Manifestation:

[4.642s][warning][jfr,system] Unable to commit. Requested size 24 too large
[4.642s][warning][jfr,system] Unable to commit. Requested size 27 too large
[4.642s][warning][jfr,system] Unable to commit. Requested size 27 too large
[4.643s][warning][jfr,system] Unable to commit. Requested size 27 too large
[4.643s][warning][jfr,system] Unable to commit. Requested size 24 too large
[4.643s][warning][jfr,system] Unable to commit. Requested size 27 too large
.,,
...
<non-deterministic crash point>

Reason:
Threads::create_vm() {
...
  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
  JvmtiExport::post_vm_initialized();

  JFR_ONLY(Jfr::on_vm_start();)
...
}

The valid offsets for the JfrJavaEventWriter are currently determined and setup during Jfr::on_vm_start().

When JFR initializes, there will be a lot of events of type jdk.ActiveSettingEvent generated. In fact, there will be enough of these events written to induce a flush of the thread local buffer. At the point of flush, because the correct offsets for the JfrJavaEventWriter are not yet properly setup, the JfrJavaEventWriter instance is not updated with new positions. This leads to the warning messages about "Unable to commit".

Unfortunately it gets worse: the offsets are statically initialized to "invalid_offset" (-1). But there are no assertions to validate that offsets have been properly initialized (i.e non "invalid_offset").

Because the oopDesc::long_field_put(int offset, jlong value) takes an int as the offset, a value of -1 is perfectly acceptable. So the value is written to oop - (1 * HeapWord), corrupting the memory address just prior to the oop.

Fix:
JfrJavaEventWriter::initialize() should move to JfrRecorder::create() to cover early initialization as well. Asserts should be added to the flush mechanism to verify correct offsets.

Longer term, maybe setting a field in an oop using a relative offset should not accept signed values, but only unsigned.

Comments
Replacing jdk8u-fix-request with link to JDK-8239140
17-02-2020

RFC: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-January/011063.html
30-01-2020

Fix Request (11u) This resolves the memory corruption with JFR. Patch applies cleanly to 11u, passes jdk_jfr tests.
24-07-2019

URL: http://hg.openjdk.java.net/jdk/jdk13/rev/51b28beb53fd User: mgronlun Date: 2019-07-02 15:48:15 +0000
02-07-2019

From Markus: "No test was added under this bug due to the relative complexities involved for reliable tests using instrumentation APIs.There should indeed be follow-up work to better test the interaction of the instrumentation APIs and JFR, some of it is tracked under JDK-8226779"
01-07-2019