JDK-8075030 : JvmtiEnv::GetObjectSize reports incorrect java.lang.Class instance size
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-03-12
  • Updated: 2016-07-07
  • Resolved: 2016-06-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b126Fixed
Related Reports
Relates :  
Description
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.

Comments
Updated wevrev: http://cr.openjdk.java.net/~shade/8075030/webrev.01/
31-05-2016

Any chance to get this fix in 9?
14-04-2016

Trivial fix: http://cr.openjdk.java.net/~shade/8075030/webrev.00/ ...fixes the java.lang.Class instance size: $ ~/trunks/jdk9-dev/build/linux-x86_64-normal-server-release/jdk/bin/java -jar target/jol-class.jar java.lang.Class object externals: ADDRESS SIZE TYPE PATH VALUE 71960baa0 104 java.lang.Class (object) 71960bb08 16 [I .componentType [] No overlap detected.
12-03-2015

-XX:+PrintFieldLayout concurs with the estimate of 104 bytes: java.lang.Class: field layout @ 12 --- instance fields start --- @ 12 "cachedConstructor" Ljava.lang.reflect.Constructor; ... @ 64 "signers_name" Ljava.lang.Object; @100 --- instance fields end --- @104 --- instance ends ---
12-03-2015

Test and executable JAR: http://cr.openjdk.java.net/~shade/8075030/Main.java http://cr.openjdk.java.net/~shade/8075030/jol-class.jar
12-03-2015