Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8227011

Starting a JFR recording in response to JVMTI VMInit and / or Java agent premain corrupts memory

    Details

    • Subcomponent:
      jfr
    • Introduced In Version:
      11
    • Resolved In Build:
      b28
    • Verification:
      Verified

      Backports

        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.

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  mgronlun Markus Grönlund
                  Reporter:
                  mgronlun Markus Grönlund
                • Votes:
                  1 Vote for this issue
                  Watchers:
                  5 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: