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

fix for 7122253 adds a JvmtiThreadState earlier than necessary

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P2
    • Resolution: Fixed
    • Affects Version/s: hs23
    • Fix Version/s: hs23
    • Component/s: hotspot
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b10
    • CPU:
      generic
    • OS:
      generic
    • Verification:
      Verified

      Backports

        Description

        The fix for the following bug:

            7122253 2/3 Instrumentation.retransformClasses() leaks
                        class bytes

        made a subtle change to when a JvmtiThreadState is added
        to a JavaThread. This subtle change exposed a bug in the
        way events are enabled in the different JVM/TI phases.
        That bug is being tracked by the following:

            7126851 3/4 cm02t001 fails due to JVMTI_ERROR_WRONG_PHASE
                        in GetThreadInfo() call

        and the failing VM/NSK test is:

            nsk/jvmti/scenarios/capability/CM02/cm02t001

        Update: here is a snippet from the test's .log file:

        [2012-01-05T03:53:13.45] ${JAVA} ${JAVA_OPTS} ${EXECUTE_CLASS} ${TEST_ARGS}
        [2012-01-05T03:53:13.47] # Actual: /export/local/common/jdk/baseline/solaris-i586/bin/java -client -Xcomp -XX:-PrintVMOptions -Dsun.jvm.hotspot.runtime.VM.disableVersionCheck=1 -XX:DefaultMaxRAMFraction=8 -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -agentlib:cm02t001=-waittime=5 nsk.jvmti.scenarios.capability.CM02.cm02t001
        [2012-01-05T03:53:13.47] # ERROR: cm02t001.c, 162: NSK_CPP_STUB3(GetThreadInfo, jvmti_env, thread, &info)
        [2012-01-05T03:53:19.89] # jvmti error: code=112, name=JVMTI_ERROR_WRONG_PHASE
        [2012-01-05T03:53:19.89] # ERROR: cm02t001.c, 162: NSK_CPP_STUB3(GetThreadInfo, jvmti_env, thread, &info)
        [2012-01-05T03:53:19.89] # jvmti error: code=112, name=JVMTI_ERROR_WRONG_PHASE
        [2012-01-05T03:53:19.89] # Test level exit status: 97


        The purpose of this bug is to restore when a JvmtiThreadState
        is added to a thread to the same semantics that existed before
        the fix for 7122253.

        Consider this code in src/share/vm/prims/jvmtiExport.cpp:

           507 class JvmtiClassFileLoadHookPoster : public StackObj {

        <snip>

           542 _state = _thread->jvmti_thread_state();
           543 if (_state != NULL) {
           544 _h_class_being_redefined = _state->get_class_being_redefined();
           545 _load_kind = _state->get_class_load_kind();
           546 // Clear class_being_redefined flag here. The action
           547 // from agent handler could generate a new class file load
           548 // hook event and if it is not cleared the new event generated
           549 // from regular class file load could have this stale redefined
           550 // class handle info.
           551 _state->clear_class_being_redefined();
           552 } else {
           553 // redefine and retransform will always set the thread state
           554 _h_class_being_redefined = (KlassHandle *) NULL;
           555 _load_kind = jvmti_class_load_kind_load;
           556 }

        Line 542 uses JavaThread::jvmti_thread_state() instead of calling
        JvmtiThreadState::state_for() so the ClassFileLoadHook event posting
        code is careful to use a JvmtiThreadState if one exists, but it does
        not allocate (and attach) one if it does not exist. When I fixed
        7122253, I missed this subtlety.

        And now consider this code in src/share/vm/classfile/classFileParser.cpp
        that was added by 7122253:

        @@ -2870,6 +2874,20 @@ instanceKlassHandle ClassFileParser::par
           _max_bootstrap_specifier_index = -1;

           if (JvmtiExport::should_post_class_file_load_hook()) {
        + // Get the cached class file bytes (if any) from the
        + // class that is being redefined.
        + JvmtiThreadState *state = JvmtiThreadState::state_for(jt);
        + KlassHandle *h_class_being_redefined =
        + state->get_class_being_redefined();
        + if (h_class_being_redefined != NULL) {
        + instanceKlassHandle ikh_class_being_redefined =
        + instanceKlassHandle(THREAD, (*h_class_being_redefined)());
        + cached_class_file_bytes =
        + ikh_class_being_redefined->get_cached_class_file_bytes();
        + cached_class_file_length =
        + ikh_class_being_redefined->get_cached_class_file_len();
        + }
        +
             unsigned char* ptr = cfs->buffer();
             unsigned char* end_ptr = cfs->buffer() + cfs->length();

        The JvmtiThreadState is the right place to find "the class
        being redefined", but the state_for() call causes a
        JvmtiThreadState to be allocated (and attached) earlier
        than it was before. If JavaThread::jvmti_thread_state() is
        used instead, then the "the class being redefined" can be
        found when it exists and no JvmtiThreadState is allocated
        when one is not needed.
        HS 23 b10 JDK 7u4/b07, 8/b22 PIT bugfix verification status: verified

        Verified on the intelsdv13 machine running the test.

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                dcubed Daniel Daugherty
                Reporter:
                dcubed Daniel Daugherty
                Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: