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

JvmtiEnv::GetObjectSize reports incorrect java.lang.Class instance size

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • 9
    • hotspot
    • None
    • b126

      JDK-6964458 introduced a special case for java.lang.Class instances in JvmtiEnv::GetObjectSize:

       JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) {
         oop mirror = JNIHandles::resolve_external_guard(object);
         NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT);

        if (mirror->klass() == SystemDictionary::Class_klass() &&
            !java_lang_Class::is_primitive(mirror)) {
          Klass* k = java_lang_Class::as_Klass(mirror);
          assert(k != NULL, "class for non-primitive mirror must exist");
          *size_ptr = (jlong)k->size() * wordSize;
        } else {
          *size_ptr = (jlong)mirror->size() * wordSize;
          }
         return JVMTI_ERROR_NONE;
       } /* end GetObjectSize */

      This, however, is incorrect: the instance size of the java.lang.Class instance itself does not depend on Klass::size().
      JOL actually detects overlaps because of that:

      $ java -jar jol-class.jar
      WARNING: Unable to attach Serviceability Agent. You can try again with super-user privileges. Use -Djol.tryWithSudo=true to try with sudo.
      WARNING: VM details, e.g. object alignment, reference size, compressed references info will be guessed.

      Running 64-bit HotSpot VM.
      Using compressed oop with 3-bit shift.
      Using compressed klass with 3-bit shift.
      Objects are 8 bytes aligned.
      Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
      Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

      java.lang.Class object externals:
                ADDRESS SIZE TYPE PATH VALUE
              7192c0728 504 java.lang.Class (object)

      Take 1
      Main$A object externals:
                ADDRESS SIZE TYPE PATH VALUE
              5c9e17308 504 java.lang.Class .c (object)
              5c9e17500 -400 **** OVERLAP **** **** OVERLAP **** **** OVERLAP ****
              5c9e17370 496 java.lang.Class .b (object)
              5c9e17560 5616077472 (something else) (somewhere else) (something else)
              718a00000 24 Main$A (object)

      Notice how the instance of B.class "overlaps" with the instance of C.class -- that's because Instrumentation.getObjectSize lied the instance size.
      Notice also the instance size for B.class and C.class is different: 496 and 504 bytes, because class C has additional method.

            shade Aleksey Shipilev
            shade Aleksey Shipilev
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: