JDK-6315555 : HPROF: should use new JVMTI heap iterate functions
  • Type: Enhancement
  • Component: tools
  • Sub-Component: hprof
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2005-08-24
  • Updated: 2010-04-02
  • Resolved: 2005-09-30
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 6
6 b55Fixed
Related Reports
Relates :  
Description
HPROF: should use new JVMTI iterate functions

Comments
SUGGESTED FIX + static jint + objectReference(jvmtiHeapReferenceKind reference_kind, + const jvmtiReferrerInfo* referrer_info, + jlong class_tag, jlong size, jlong* tag_ptr, + jlong* referrer_tag_ptr) + { + ObjectIndex object_index; + SiteIndex object_site_index; + jint referrer_index; + RefIndex ref_index; + RefIndex prev_ref_index; + ObjectIndex referrer_object_index; + jlong object_tag; + + HPROF_ASSERT(tag_ptr!=NULL); + HPROF_ASSERT((*referrer_tag_ptr)!=(jlong)0); + + switch ( reference_kind ) { + case JVMTI_HEAP_REFERENCE_FIELD: + referrer_index = referrer_info->field.index; + break; + case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT: + referrer_index = referrer_info->array.index; + break; + case JVMTI_HEAP_REFERENCE_STATIC_FIELD: + referrer_index = referrer_info->field.index; + break; + case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: + referrer_index = referrer_info->constant_pool.index; + break; + default: + referrer_index = 0; + break; + } + + if ( (*referrer_tag_ptr) != (jlong)0 ) { + referrer_object_index = tag_extract((*referrer_tag_ptr)); + } else { + return JVMTI_VISIT_OBJECTS; + } + + object_tag = *tag_ptr; + if ( object_tag != (jlong)0 ) { + object_index = tag_extract(object_tag); + } else { + SiteIndex site_index; + + site_index = site_find_or_create(find_cnum(class_tag), + gdata->system_trace_index); + object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM, + gdata->unknown_thread_serial_num); + object_tag = tag_create(object_index); + *tag_ptr = object_tag; + } + + /* Save reference information */ + prev_ref_index = object_get_references(referrer_object_index); + ref_index = reference_new(prev_ref_index, reference_kind, + class_tag, size, object_tag, referrer_index); + object_set_references(referrer_object_index, ref_index); + + return JVMTI_VISIT_OBJECTS; + } + + /* FollowReferences object_reference_callback */ + static jint JNICALL + cbObjectReference(jvmtiHeapReferenceKind reference_kind, + const jvmtiReferrerInfo* referrer_info, + jlong class_tag, jlong size, jlong* tag_ptr, + jlong* referrer_tag_ptr, jint length, void* user_data) + { + ObjectIndex object_index; + SiteIndex object_site_index; + + /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit + * are allowed here (see the JVMTI Spec). + */ + + switch ( reference_kind ) { + + case JVMTI_HEAP_REFERENCE_CLASS: + case JVMTI_HEAP_REFERENCE_FIELD: + case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT: + case JVMTI_HEAP_REFERENCE_CLASS_LOADER: + case JVMTI_HEAP_REFERENCE_SIGNERS: + case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN: + case JVMTI_HEAP_REFERENCE_INTERFACE: + case JVMTI_HEAP_REFERENCE_STATIC_FIELD: + case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: + return objectReference(reference_kind, referrer_info, + class_tag, size, tag_ptr, referrer_tag_ptr); + break; + + case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: { + SerialNumber trace_serial_num; + SerialNumber gref_serial_num; + TraceIndex trace_index; + + setup_tag_on_root(tag_ptr, class_tag, size, + gdata->unknown_thread_serial_num, + &object_index, &object_site_index); + if ( object_site_index != 0 ) { + SiteKey *pkey; + + pkey = get_pkey(object_site_index); + trace_index = pkey->trace_index; + } else { + trace_index = gdata->system_trace_index; + } + trace_serial_num = trace_get_serial_number(trace_index); + gref_serial_num = gdata->gref_serial_number_counter++; + io_heap_root_jni_global(object_index, gref_serial_num, + trace_serial_num); + } + break; + + case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: { + char *sig; + SerialNumber class_serial_num; + + setup_tag_on_root(tag_ptr, class_tag, size, + gdata->unknown_thread_serial_num, + &object_index, &object_site_index); + sig = "Unknown"; + class_serial_num = 0; + if ( object_site_index != 0 ) { + SiteKey *pkey; + + pkey = get_pkey(object_site_index); + sig = string_get(class_get_signature(pkey->cnum)); + class_serial_num = class_get_serial_number(pkey->cnum); + } + io_heap_root_system_class(object_index, sig, class_serial_num); + } + break; + + case JVMTI_HEAP_REFERENCE_MONITOR: { + setup_tag_on_root(tag_ptr, class_tag, size, + gdata->unknown_thread_serial_num, + &object_index, NULL); + io_heap_root_monitor(object_index); + } + break; + + case JVMTI_HEAP_REFERENCE_STACK_LOCAL: { + SerialNumber thread_serial_num; + + if ( (*tag_ptr) != (jlong)0 ) { + object_index = tag_extract(*tag_ptr); + thread_serial_num = object_get_thread_serial_number(object_index); + } else { + SiteIndex site_index; + jlong thread_tag; + + thread_tag = referrer_info->stack_local.thread_tag; + + site_index = site_find_or_create(find_cnum(class_tag), + gdata->system_trace_index); + if ( thread_tag != (jlong)0 ) { + ObjectIndex thread_object_index; + + thread_object_index = tag_extract(thread_tag); + thread_serial_num = + object_get_thread_serial_number(thread_object_index); + } else { + thread_serial_num = gdata->unknown_thread_serial_num; + } + object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM, + thread_serial_num); + /* Create and set the tag. */ + *tag_ptr = tag_create(object_index); + } + + HPROF_ASSERT(thread_serial_num!=0); + HPROF_ASSERT(object_index!=0); + io_heap_root_java_frame(object_index, thread_serial_num, referrer_info->stack_local.depth); + } + break; + + case JVMTI_HEAP_REFERENCE_JNI_LOCAL: { + SerialNumber thread_serial_num; + + if ( (*tag_ptr) != (jlong)0 ) { + object_index = tag_extract(*tag_ptr); + thread_serial_num = object_get_thread_serial_number(object_index); + } else { + SiteIndex site_index; + jlong thread_tag; + + thread_tag = referrer_info->jni_local.thread_tag; + + site_index = site_find_or_create(find_cnum(class_tag), + gdata->system_trace_index); + if ( thread_tag != (jlong)0 ) { + ObjectIndex thread_object_index; + + thread_object_index = tag_extract(thread_tag); + thread_serial_num = + object_get_thread_serial_number(thread_object_index); + } else { + thread_serial_num = gdata->unknown_thread_serial_num; + } + object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM, + thread_serial_num); + /* Create and set the tag. */ + *tag_ptr = tag_create(object_index); + } + + HPROF_ASSERT(thread_serial_num!=0); + HPROF_ASSERT(object_index!=0); + io_heap_root_jni_local(object_index, thread_serial_num, referrer_info->jni_local.depth); + } + break; + + case JVMTI_HEAP_REFERENCE_THREAD: { + SerialNumber thread_serial_num; + SerialNumber trace_serial_num; + TraceIndex trace_index; + + if ( (*tag_ptr) != (jlong)0 ) { + setup_tag_on_root(tag_ptr, class_tag, size, 0, + &object_index, &object_site_index); + trace_index = site_get_trace_index(object_site_index); + /* Hopefully the ThreadStart event put this thread's + * correct serial number on it's object. + */ + thread_serial_num = object_get_thread_serial_number(object_index); + } else { + /* Rare situation that a Thread object is not tagged. + * Create special unique thread serial number in this + * case, probably means we never saw a thread start + * or thread end, or even an allocation of the thread + * object. + */ + thread_serial_num = gdata->thread_serial_number_counter++; + setup_tag_on_root(tag_ptr, class_tag, size, + thread_serial_num, + &object_index, &object_site_index); + trace_index = gdata->system_trace_index; + } + trace_serial_num = trace_get_serial_number(trace_index); + /* Issue thread object (must be before thread root) */ + io_heap_root_thread_object(object_index, + thread_serial_num, trace_serial_num); + /* Issue thread root */ + io_heap_root_thread(object_index, thread_serial_num); + } + break; + + case JVMTI_HEAP_REFERENCE_OTHER: { + setup_tag_on_root(tag_ptr, class_tag, size, + gdata->unknown_thread_serial_num, + &object_index, NULL); + io_heap_root_unknown(object_index); + } + break; + + default: + setup_tag_on_root(tag_ptr, class_tag, size, + gdata->unknown_thread_serial_num, + NULL, NULL); + break; + + } + + return JVMTI_VISIT_OBJECTS; + } + + void site_heapdump(JNIEnv *env) { *************** *** 693,698 **** --- 744,751 ---- rawMonitorEnter(gdata->data_access_lock); { + jvmtiHeapCallbacks heapCallbacks; + struct { int i; } user_data; /* FIXUP */ user_data.i = 0; *************** *** 720,727 **** trace_get_serial_number(gdata->system_trace_index)); /* Iterate over heap and get the real stuff */ ! iterateOverReachableObjects(&root_object, &stack_object, ! &reference_object, (void*)&user_data); /* Process reference information. */ object_reference_dump(env); --- 773,784 ---- trace_get_serial_number(gdata->system_trace_index)); /* Iterate over heap and get the real stuff */ ! (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks)); ! heapCallbacks.object_reference_callback = &cbObjectReference; ! heapCallbacks.field_primitive_value_callback = NULL; /*FIXUP*/ ! heapCallbacks.array_primitive_value_callback = NULL; /*FIXUP*/ ! heapCallbacks.string_primitive_value_callback = NULL; /*FIXUP*/ ! followReferences(&heapCallbacks, (void*)&user_data); /* Process reference information. */ object_reference_dump(env);
27-08-2005

SUGGESTED FIX Changes are pretty significant and are tied together with the primitive data bug fix. Mostly isolated to hprof_site,c and hprof_references.c See 4965057. Had to use FollowReferences() to fix 4965057.
27-08-2005

EVALUATION See suggested fix.
27-08-2005