java.lang.instrument.Instrumentation.getObjectSize for java.lang.Class instance

David Holmes david.holmes at oracle.com
Sun Dec 16 18:01:18 PST 2012


On 15/12/2012 4:40 AM, Krystal Mok wrote:
> Hi Peter,
>
> Which version of JDK are you using? Assuming you're using a JDK6/JDK7
> version released to date, the actual implementation for
> j.l.i.Instrumentation.getObjectSize() is as follows:
>
> jvmtiError
> 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()) {
>      if (!java_lang_Class::is_primitive(mirror)) {
>          mirror = java_lang_Class::as_klassOop(mirror);
>          assert(mirror != NULL, "class for non-primitive mirror must exist");
>      }
>    }
>
>    *size_ptr = mirror->size() * wordSize;
>    return JVMTI_ERROR_NONE;
> } /* end GetObjectSize */
>
> So there's special handling for j.l.Class instances' size: it's
> reporting the size of the klassOop (the VM internal type that holds
> the metadata). That's why changing the number of fields in j.l.Class
> doesn't affect the result of getObjectSize(clazz).

I had slightly different variants in the testing code I previously put 
together for JEP-149 - see below.

But the key thing is that you need two different API's here: one for 
regular objects and one for Class instances. To that end 
Instrumentation.getObjectSize is not that useful for Class instances, 
but I think the implementation chosen is not what people would generally 
want when asking about Class sizes.

David

+// Return the size of an instance of cls
+JVM_ENTRY(jlong, JVM_Sizeof(JNIEnv *env, jclass ignored, jclass cls))
+  JVMWrapper("JVM_Sizeof");
+  // Check if we have null pointers
+  if (cls == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  oop mirror = JNIHandles::resolve_non_null(cls);
+
+  // exclude primitives and arrays
+  if (java_lang_Class::is_primitive(mirror) /*|| is array */) {
+    THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+  }
+  klassOop klass = java_lang_Class::as_klassOop(mirror);
+  return align_object_size(instanceKlass::cast(klass)->size_helper()) 
<< LogHeapWordSize;
+JVM_END
+
+// Return the size of cls - which is the base size for any instance
+// of java.lang.Class plus any static fields for this particular Class
+JVM_ENTRY(jlong, JVM_SizeofClass(JNIEnv *env, jclass ignored, jclass cls))
+  JVMWrapper("JVM_SizeofClass");
+  // Check if we have null pointers
+  if (cls == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+  oop mirror = JNIHandles::resolve_non_null(cls);
+  return mirror->size() << LogHeapWordSize;
+JVM_END


More information about the hotspot-runtime-dev mailing list