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

FramePop event contains incorrect info when popping by exception or VM crash.

    Details

    • Subcomponent:
    • Resolved In Build:
      b46
    • CPU:
      sparc
    • OS:
      solaris_8
    • Verification:
      Verified

      Description



      Name: vsR10008 Date: 10/10/2003



      JVMTI spec for FramePop event says:

      "Frame pop events are generated upon exit from a single method in a single frame
      as specified in a call to NotifyFramePop. This is true whether termination is caused
      by executing its return instruction or by throwing an exception to its caller (see
      was_popped_by_exception)"

      RI generates FramePop event when popping is caused by exception, but this
      event contains incorrect "was_popped_by_exception" parameter and
      wrong method ID. It looks like RI misses popping stack frame when
      the exception is being propagated and generates event in wrong place - on
      exit from another method when stack depth becomes equal to the level
      specified in NotifyFramePop.

      To reproduce this bug please run on Solaris the following sh script
      (do not forget to change JDK_PATH var):

      ---- File: runme.sh ---------------------------------------------------
      JDK_PATH="/java/re/jdk/1.5.0/latest/binaries/solaris-sparc"

      JVMTI_H_PATH="${JDK_PATH}/include"
      CC="cc"

      echo "...creating a.c"
      cat - > a.c <<EOF

      #include <stdio.h>
      #include "jvmti.h"

      static jvmtiEnv *jvmti = NULL;
      static jvmtiCapabilities capa;
      static jvmtiEventCallbacks callbacks;

      void printMethod(jvmtiEnv *jvmti,
                       JNIEnv *jni,
                       jmethodID mid) {
           jvmtiError err;
           char *name;
           char *sig;
           char *gsig;

           err = (*jvmti)->GetMethodName(jvmti, mid, &name, &sig, &gsig);
           if (err != JVMTI_ERROR_NONE) {
               printf("GetMethodName:%d\n", err);
               return;
           }
           printf("Method:%s%s\n", name, sig);
      }


      void JNICALL
      FramePop(jvmtiEnv *jvmti_env,
                   JNIEnv* jni_env,
                   jthread thread,
                   jmethodID method,
                   jboolean was_popped_by_exception) {
          printf("==========> FramePop event: popped by %s\n",
             (was_popped_by_exception == JNI_TRUE?"exception":"return"));
          printMethod(jvmti_env, jni_env, method);
      }

      JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
           jvmtiError err;
           jint res;

           memset(&capa, 0, sizeof(jvmtiCapabilities));
           capa.can_generate_frame_pop_events = 1;

           res = (*jvm)->GetEnv(jvm, (void **) &jvmti,
                 JVMTI_VERSION_1_0);

           if (res != JNI_OK || jvmti == NULL) {
               return JNI_ERR;
           }
           err = (*jvmti)->AddCapabilities(jvmti, &capa);
           if (err != JVMTI_ERROR_NONE && err != JVMTI_ERROR_NOT_AVAILABLE) {
               return JNI_ERR;
           }

           printf("Loaded!\n");
           return JNI_OK;
      }

      JNIEXPORT void JNICALL
      Java_a_dummy(JNIEnv *env, jclass cls) {
      }

      JNIEXPORT void JNICALL
      Java_a_pop(JNIEnv *env, jclass cls, jthrowable t) {
             jvmtiError err;
             jint res;
             char *errn;

             callbacks.FramePop = &FramePop;
             err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
             (*jvmti)->GetErrorName(jvmti, err, &errn);
             printf("SetEventCallbacks, error code: %s\n", errn);

             err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,JVMTI_EVENT_FRAME_POP, NULL);
             (*jvmti)->GetErrorName(jvmti, err, &errn);
             printf("SetEventNotificationMode, error code: %s\n", errn);

             err = (*jvmti)->NotifyFramePop(jvmti, NULL, 1);
             (*jvmti)->GetErrorName(jvmti, err, &errn);
             printf("NotifyFramePop, error code 2: %s\n", errn);

             (*env)->Throw(env, t);

             printf("Finished!\n");
      }

      EOF

      echo "...creating liba.so"

      ${CC} -G -KPIC -o liba.so -I${JDK_PATH}/include -I${JDK_PATH}/include/solaris -I${JVMTI_H_PATH} a.c

      echo "...creating a.java"

      cat - > a.java <<EOF
      public class a extends Exception {
           native static void pop(Throwable t) throws a;
           native static void dummy();
           public static void main(String args[]) {
               System.loadLibrary("a");
               try {
                  popped(new a());
               } catch (a ex) {
               }
               dummy();
           }
           public static void popped(Throwable t) throws a {
               pop(t);
           }
      }

      EOF

      echo "...creating a.class"

      ${JDK_PATH}/bin/javac -d . a.java

      echo "...running a.class"
      LD_LIBRARY_PATH=. CLASSPATH=. ${JDK_PATH}/bin/java -showversion -agentlib:a a
      -----------------------------------------------------------------------

      Running on b21, execution log is as follows:

      ----------------------------------------------------------------------
      ...creating a.c
      ...creating liba.so
      ...creating a.java
      ...creating a.class
      ...running a.class
      Loaded!
      java version "1.5.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b21)
      Java HotSpot(TM) Client VM (build 1.5.0-beta-b21, mixed mode)

      SetEventCallbacks, error code: JVMTI_ERROR_NONE
      SetEventNotificationMode, error code: JVMTI_ERROR_NONE
      NotifyFramePop, error code 2: JVMTI_ERROR_NONE
      Finished!
      ==========> FramePop event: popped by return
      Method:dummy()V
      ----------------------------------------------------------------------

      Two bottom lines show that "was_popped_by_exception" parameter of event
      is not equal to JNI_TRUE and popped method is "dummy()" whereas
      "popped()" should be. It is strange enough that pop event is
      triggered in the NATIVE method - JVMTI spec prohibits setting pop
      notification for native frame (see function NotifyFramePop and
      error code JVMTI_ERROR_OPAQUE_FRAME).

      This bug is reproducible on build 21 and affects JCK JVMTI test:
      vm/jvmti/FramePop/fpop001/fpop00101/fpop00101.html

      ======================================================================


      VM could crash if the can_generate_exception capability is not added.


      see attached script r1.sh to reproduce this crash.

      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b41)
      Java HotSpot(TM) Client VM (build 1.5.0-beta2-b41-debug, mixed mode)

      NotifyFramePop, error code 2: JVMTI_ERROR_NONE
      Finished!
      # To suppress the following error report, specify this argument
      # after -XX: or in .hotspotrc: SuppressErrorAt=/jvmtiThreadState.cpp:213]
      #
      # An unexpected error has been detected by HotSpot Virtual Machine:
      #
      # Internal Error (/BUILD_AREA/jdk1.5.0/hotspot/src/share/vm/prims/jvmtiThreadState.cpp, 213 [ Patched ]), pid=26922, tid=1
      #
      # Java VM: Java HotSpot(TM) Client VM (1.5.0-beta2-b41-debug mixed mode)
      #
      # Error: assert(_cur_stack_depth == count_frames(),"cur_stack_depth out of sync")
      # An error report file with more information is saved as hs_err_pid26922.log
      #



        Attachments

          Activity

            People

            • Assignee:
              swamyv Swamy Venkataramanappa
              Reporter:
              atwosunw A2 A2 (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Imported:
                Indexed: