ObjectIndex object_new(SiteIndex site_index, jint size, ObjectKind kind, SerialNumber thread_serial_num) { ObjectIndex index; ObjectKey key; static ObjectKey empty_key; key = empty_key; key.site_index = site_index; key.size = size; key.kind = kind; if ( gdata->heap_dump ) { static ObjectInfo empty_info; ObjectInfo i; i = empty_info; i.thread_serial_num = thread_serial_num; key.serial_num = gdata->object_serial_number_counter++; index = table_create_entry(gdata->object_table, &key, (int)sizeof(ObjectKey), &i); } else { key.serial_num = class_get_serial_number(site_get_class_index(site_index)); index = table_find_or_create_entry(gdata->object_table, &key, (int)sizeof(ObjectKey), NULL, NULL); } site_update_stats(site_index, size, 1); return index; }
void site_write(JNIEnv *env, int flags, double cutoff) { HPROF_ASSERT(gdata->site_table!=NULL); LOG3("site_write", "flags", flags); if (flags & SITE_FORCE_GC) { runGC(); } HPROF_ASSERT(gdata->total_live_bytes!=0); rawMonitorEnter(gdata->data_access_lock); { IterateInfo iterate; int site_table_size; double accum_percent; void * comment_str; int i; int cutoff_count; int nbytes; accum_percent = 0; site_table_size = table_element_count(gdata->site_table); (void)memset(&iterate, 0, sizeof(iterate)); nbytes = site_table_size * (int)sizeof(SiteIndex); if ( nbytes > 0 ) { iterate.site_nums = HPROF_MALLOC(nbytes); (void)memset(iterate.site_nums, 0, nbytes); } iterate.count = 0; iterate.changed_only = flags & SITE_DUMP_INCREMENTAL; table_walk_items(gdata->site_table, &collect_iterator, &iterate); site_table_size = iterate.count; if (flags & SITE_SORT_BY_ALLOC) { comment_str = "allocated bytes"; qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex), &qsort_compare_allocated_bytes); } else { comment_str = "live bytes"; qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex), &qsort_compare_live_bytes); } trace_output_unmarked(env); cutoff_count = 0; for (i = 0; i < site_table_size; i++) { SiteInfo *info; SiteIndex index; double ratio; index= iterate.site_nums[i]; HPROF_ASSERT(index!=0); info = get_info(index); ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes; if (ratio < cutoff) { break; } cutoff_count++; } io_write_sites_header( comment_str, flags, cutoff, gdata->total_live_bytes, gdata->total_live_instances, gdata->total_alloced_bytes, gdata->total_alloced_instances, cutoff_count); for (i = 0; i < cutoff_count; i++) { SiteInfo *info; SiteKey *pkey; SiteIndex index; char *class_signature; double ratio; index = iterate.site_nums[i]; pkey = get_pkey(index); info = get_info(index); ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes; accum_percent += ratio; class_signature = string_get(class_get_signature(pkey->cnum)); io_write_sites_elem(i + 1, ratio, accum_percent, class_signature, class_get_serial_number(pkey->cnum), trace_get_serial_number(pkey->trace_index), info->n_live_bytes, info->n_live_instances, info->n_alloced_bytes, info->n_alloced_instances); } io_write_sites_footer(); table_walk_items(gdata->site_table, &mark_unchanged_iterator, NULL); if ( iterate.site_nums != NULL ) { HPROF_FREE(iterate.site_nums); } } rawMonitorExit(gdata->data_access_lock); }
/* 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; }