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

Instrumentation.getObjectSize triggers JVM crash in JPLISAssert in shutdown

XMLWordPrintable

    • b26
    • x86
    • linux
    • Verified

        FULL PRODUCT VERSION :
        java version "1.6.0_01"
        Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
        Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)


        ADDITIONAL OS VERSION INFORMATION :
        Linux d 2.6.18.5-XXX-mixed64-32 #1 SMP XXX x86_64 GNU/Linux
        System is a modified ubuntu dapper.

        EXTRA RELEVANT SYSTEM CONFIGURATION :
        NPTL 2.3.6 from glibc 2.3.6.

        A DESCRIPTION OF THE PROBLEM :
        Calling Instrumentation.getObjectSize() while the JVM is attempting to exit causes the JVM to crash on an internal assertion instead of exiting gracefully.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Build the attached source into a jar and run with a command line like:
        ./javac-1.6.0_01 TriggerJPLISAssert.java && jar -cfm triggerjplisassert.jar manifest.mf TriggerJPLISAssert.class TriggerJPLISAssert\$RoundAndRound.class && ./java-1.6.0_01 -server -javaagent:triggerjplisassert.jar -jar triggerjplisassert.jar


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Nothing should be output other than the "exiting" message. The daemon threads should be quietly shut down as they are if one comments out the getObjectSize() line.
        ACTUAL -
        A (variable) number of JPLISAssert failure messages are printed after the "exiting" message is printed by the main thread. Different runs produce a different number of messages.

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        Sample output:

        exiting
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296

        no other stderr/stdout/core/hs_err_pid output.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        manifest.mf file:
        Premain-Class: TriggerJPLISAssert
        Main-Class: TriggerJPLISAssert

        TriggerJPLISAssert.java file:
        import java.lang.instrument.Instrumentation;

        public class TriggerJPLISAssert {
          private static Instrumentation instrumentation;

          private TriggerJPLISAssert() { }

          public static void premain(String agentArgs, Instrumentation inst) {
            instrumentation = inst;
          }

          public static void main(String args[]) throws InterruptedException {
            RoundAndRound[] threads = new RoundAndRound[10];
            for (int i=0; i<threads.length; ++i) {
              threads[i] = new RoundAndRound(instrumentation);
              threads[i].start();
            }
            Thread.sleep(1); // let all threads get going in their loops
            System.out.println("exiting");
          }

          private static class RoundAndRound extends Thread {
            private final Instrumentation inst;
            private final Object anObject;
            public RoundAndRound(Instrumentation inst) {
              this.inst = inst;
              this.anObject = new Object();
              setDaemon(true);
            }
            public void run() {
              long sum = 0;
              while (true) {
                sum += inst.getObjectSize(anObject);
              }
            }
          }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Adding a shutdown hook with Runtime.getRuntime().addShutdownHook() which sets an application-specific "stop calling getObjectSize()" flag seems to prevent the crashes and lets my application exit gracefully.

        This is an unsatisfactory long-term workaround because it requires adding synchronization (around the shutdown-indicating flag) for each invocation of getObjectSize(), or else living with a slight race condition by making the flag volatile and hoping shutdown doesn't proceed beyond the point that triggers the assert between the check of the flag and the call to getObjectSize().
        I've copied the test from the description and added it to the
        INSTRUMENT_REGRESSION test suite as StressGetObjectSizeTest.java.
        Using the test I can reproduce the failure:

        java version "1.7.0-ea"
        Java(TM) SE Runtime Environment (build 1.7.0-ea-b24)
        Java HotSpot(TM) Client VM (build 12.0-b01, mixed mode, sharing)

        STATUS:Passed.
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        *** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
        at ../../../src/share/instrument/JPLISAgent.c line: 1328
        result: Passed. Execution successful

        Obviously JavaTest/JTREG thinks the test has passed so I'll
        have to tweak it a bit to show up as a failure.
        The following new test will fail without the fix for this
        bug in a promoted JDK:

            java/lang/instrument/StressGetObjectSizeTest.sh

              dcubed Daniel Daugherty
              ndcosta Nelson Dcosta (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: