/* JVMTI callback function. */ static jvmtiIterationControl JNICALL stack_object(jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void *user_data) { /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit * are allowed here (see the JVMTI Spec). */ ObjectIndex object_index; SerialNumber thread_serial_num; HPROF_ASSERT(tag_ptr!=NULL); if ( (*tag_ptr) != (jlong)0 ) { object_index = tag_extract(*tag_ptr); thread_serial_num = object_get_thread_serial_number(object_index); thread_serial_num = checkThreadSerialNumber(thread_serial_num); } else { SiteIndex site_index; 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); thread_serial_num = checkThreadSerialNumber(thread_serial_num); } 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); switch ( root_kind ) { case JVMTI_HEAP_ROOT_STACK_LOCAL: io_heap_root_java_frame(object_index, thread_serial_num, depth); break; case JVMTI_HEAP_ROOT_JNI_LOCAL: io_heap_root_jni_local(object_index, thread_serial_num, depth); break; default: break; } return JVMTI_ITERATION_CONTINUE; }
/* FollowReferences heap_reference_callback */ static jint JNICALL cbReference(jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data) { ObjectIndex object_index; /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit * are allowed here (see the JVMTI Spec). */ HPROF_ASSERT(tag_ptr!=NULL); HPROF_ASSERT(class_tag!=(jlong)0); if ( class_tag == (jlong)0 ) { /* We can't do anything with a class_tag==0, just skip it */ return JVMTI_VISIT_OBJECTS; } switch ( reference_kind ) { 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, reference_info, class_tag, size, tag_ptr, referrer_tag_ptr, length); case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: { SerialNumber trace_serial_num; SerialNumber gref_serial_num; TraceIndex trace_index; SiteIndex object_site_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; SiteIndex object_site_index; 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; jlong thread_tag; thread_tag = reference_info->stack_local.thread_tag; localReference(tag_ptr, class_tag, thread_tag, size, &object_index, &thread_serial_num); io_heap_root_java_frame(object_index, thread_serial_num, reference_info->stack_local.depth); } break; case JVMTI_HEAP_REFERENCE_JNI_LOCAL: { SerialNumber thread_serial_num; jlong thread_tag; thread_tag = reference_info->jni_local.thread_tag; localReference(tag_ptr, class_tag, thread_tag, size, &object_index, &thread_serial_num); io_heap_root_jni_local(object_index, thread_serial_num, reference_info->jni_local.depth); } break; case JVMTI_HEAP_REFERENCE_THREAD: { SerialNumber thread_serial_num; SerialNumber trace_serial_num; TraceIndex trace_index; SiteIndex object_site_index; TlsIndex tls_index; /* It is assumed that tag_ptr is referring to a * java.lang.Thread object here. */ 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; } /* Get tls_index and set in_heap_dump, if we find it. */ tls_index = tls_find(thread_serial_num); if ( tls_index != 0 ) { tls_set_in_heap_dump(tls_index, 1); } 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: /* Ignore anything else */ break; } return JVMTI_VISIT_OBJECTS; }