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

JVMPI class dump fails to include objects from the constant pool.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Fix
    • P4
    • tbd
    • 1.4.2
    • vm-legacy
    • x86
    • windows_2000

    Description



      Name: rmT116609 Date: 08/12/2003


      FULL PRODUCT VERSION :
      java version "1.4.2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
      Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

      FULL OS VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      During a heap dump the JVMPI does not include and objects from the constant pools of the classes in the class dumps.

      The format specifies the the constant pool is part of this dump:
        From http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html#heap_dump_format
      However it is clear that those elements are omitted.

      JVMPI_GC_CLASS_DUMP
      (dump of a class object) jobjectID class
      jobjectID super
      jobjectID class loader
      jobjectID signers
      jobjectID protection domain
      jobjectID class name (a String object, may be NULL)
      void * reserved
      u4 instance size (in bytes)
      [jobjectID]* interfaces
      u2 size of constant pool
      [u2, constant pool index,
       ty, type,
       vl]* value
      [vl]* static field values

      The problem is in commented in the JVM sourcecode (my VM source code).
      SRCDIR/hotspot/src/share/vm/prims/jvmpi.cpp in the function
      void dump_klass(klassOop klass)



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Trigger a heap dump event with the JVMPI interface with the RequestEvent function.

      For any class note that the "u2 size of constant pool" entry of is 0.

      Alternately:
      You can run my testcase for any program and hit control-break.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I was expecting the at least all of the elements of the constant pools or at least the objects.




      ACTUAL -
      No constant pool entrys are reported.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      #include <jvmpi.h>
      #include <winsock.h> //for ntohl, ntohs


      JVMPI_Interface *jvmpiInterface;

      /* Globals for callback accesses */
      char* className;
      jint numInterfaces;

      jint numStatics;
      char* staticSigChars; //we just need the width of the static values

      void FetchClassInfo( jobjectID classID )
      {
          if( jvmpiInterface->RequestEvent( JVMPI_EVENT_CLASS_LOAD, classID ) != JVMPI_SUCCESS )
          {
              printf( "RequestEvent: call failed with classID 0x%X!\n", classID );
              exit(1);
          }
      }

      void ScanHeap( JVMPI_Event *event )
      {
          char *heapPtr = event->u.heap_dump.begin;

          /* We will skip over everything except the JVMPI_GC_CLASS_DUMP entrys */
          while( heapPtr < event->u.heap_dump.end )
          {
              switch( *heapPtr++ )
              {
                  case JVMPI_GC_ROOT_UNKNOWN:
                      heapPtr += sizeof(jobjectID);
                      break;

                  case JVMPI_GC_ROOT_JNI_GLOBAL:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(jobject);
                      break;

                  case JVMPI_GC_ROOT_JNI_LOCAL:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(JNIEnv *);
                      heapPtr += sizeof(unsigned int);
                      break;

                  case JVMPI_GC_ROOT_JAVA_FRAME:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(JNIEnv *);
                      heapPtr += sizeof(unsigned int);
                      break;

                  case JVMPI_GC_ROOT_NATIVE_STACK:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(JNIEnv *);
                      break;

                  case JVMPI_GC_ROOT_STICKY_CLASS:
                      heapPtr += sizeof(jobjectID);
                      break;

                  case JVMPI_GC_ROOT_THREAD_BLOCK:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(JNIEnv *);
                      break;

                  case JVMPI_GC_ROOT_MONITOR_USED:
                      heapPtr += sizeof(jobjectID);
                      break;

                  case JVMPI_GC_CLASS_DUMP:{
                      jobjectID classID;
                      jint i;

                      classID = *( (jobjectID*)heapPtr );
                      FetchClassInfo( classID );
                      printf("CLASS %s\n", className );
                      //skip everything
                      heapPtr += 6*sizeof(jobjectID) +
                                  sizeof(void *) +
                                  sizeof(unsigned int) +
                                  numInterfaces*sizeof(jobjectID);



      //
      //THIS IS num constants entry.
      //
                      printf(" number of constant pool entries is %d\n\n", ntohs(*((unsigned short*)heapPtr) ) );
                      heapPtr += sizeof(unsigned short);

                      // Note that I would traverse the constant pool entries if they were there right here.

                      //SKIP the static values for the next entry
                      for( i=0; i<numStatics; ++i )
                      {
                          switch( staticSigChars[i] )
                          {
                              case 'L':
                              case '[':
                                  heapPtr += sizeof(jobjectID);
                                  break;
                              case 'Z':
                              case 'B':
                                  heapPtr += sizeof(unsigned char);
                                  break;
                              case 'S':
                              case 'C':
                                  heapPtr += sizeof(unsigned short);
                                  break;
                              case 'F':
                              case 'I':
                                  heapPtr += sizeof(unsigned int);
                                  break;
                              case 'D':
                              case 'J':
                                  heapPtr += sizeof(jvalue);
                                  break;
                              default:
                                  printf("Signature type error for static value!");
                                  exit(1);
                          }
                      }


                      free(className);
                      free(staticSigChars);

                      break;

                  }case JVMPI_GC_INSTANCE_DUMP:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += sizeof(jobjectID);
                      heapPtr += ntohl(*( (unsigned int*)heapPtr ) );
                      heapPtr += sizeof(unsigned int);
                      break;

                  case JVMPI_GC_OBJ_ARRAY_DUMP:
                      heapPtr += sizeof(jobjectID);
                      heapPtr += ntohl(*( (unsigned int*)heapPtr )) * sizeof(jobjectID);
                      heapPtr += sizeof(jobjectID) + sizeof(unsigned int);
                      break;

                  case JVMPI_GC_PRIM_ARRAY_DUMP:
                  {
                      unsigned int length;
                      //(dump of a primitive array)
                      //jobjectID array object
                      //u4 number of elements
                      //ty element type
                      //[vl]* elements
                      heapPtr += sizeof(jobjectID);

                      length = ntohl( *( (unsigned int *)heapPtr ) );
                      heapPtr += sizeof(unsigned int);
                      // look ahead to extract the array element type.
                      switch( *heapPtr++ )
                      {
                        case JVMPI_BOOLEAN:
                        case JVMPI_BYTE:
                            //type length + typetag + values*width
                            heapPtr += length*1;
                            break;

                        case JVMPI_CHAR:
                        case JVMPI_SHORT:
                            heapPtr += length*2;
                            break;

                        case JVMPI_INT:
                        case JVMPI_FLOAT:
                            heapPtr += length*4;
                            break;

                        case JVMPI_LONG:
                        case JVMPI_DOUBLE:
                            heapPtr += length*8;
                            break;
                        default:
                          printf("Primitive array type error 0x%X\n", *((unsigned char*)(heapPtr-1)) );
                          exit(1);
                      }
                      break;
                  }
                  default:
                      printf("ERROR: invalid tag\n");
                      exit(1);
              } //end switch
          } //end while
          printf("Scan finished\n");
      }

      void notifyEvent( JVMPI_Event *event )
      {
          switch( event->event_type )
          {
          case JVMPI_EVENT_DATA_DUMP_REQUEST:
              jvmpiInterface->RequestEvent( JVMPI_EVENT_HEAP_DUMP, NULL );
              break;
          case JVMPI_EVENT_HEAP_DUMP | JVMPI_REQUESTED_EVENT:
              ScanHeap( event );
              break;
          case JVMPI_EVENT_CLASS_LOAD | JVMPI_REQUESTED_EVENT:{
              jint i;
              className = (char *)strdup( event->u.class_load.class_name );
              numInterfaces = event->u.class_load.num_interfaces;
              numStatics = event->u.class_load.num_static_fields;
              staticSigChars = (char *)malloc(numStatics);
              for(i=0; i<numStatics; ++i )
                  staticSigChars[i] = *event->u.class_load.statics[i].field_signature;
              break;
          }
          }

      }

      JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
      {
          jint res = (*jvm)->GetEnv(jvm, (void **)&jvmpiInterface, JVMPI_VERSION_1);
          if (res < 0)
          {
              return JNI_ERR;
          }


          if( jvmpiInterface->EnableEvent( JVMPI_EVENT_DATA_DUMP_REQUEST, NULL ) != JVMPI_SUCCESS ){
              fprintf( stderr, "nprof> Cntrl-Break handler set failed.\n" );
              return JNI_ERR;
          }

          //
          // other startup tasks
          //

          jvmpiInterface->NotifyEvent = notifyEvent;

          fprintf( stderr, "nprof> JVMPI Version: 0x %X... ok \n\n",jvmpiInterface->version );
          return JNI_OK;
      }
      ---------- END SOURCE ----------
      (Incident Review ID: 198737)
      ======================================================================

      Attachments

        Activity

          People

            Unassigned Unassigned
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: