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

    XMLWordPrintable

Details

    • jfr
    • 11
    • b28
    • 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

                mgronlun Markus Grönlund
                mgronlun Markus Grönlund
                Votes:
                1 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved: