/* Printf of an element for gdata->check_fd */ static void check_printf_val(HprofType ty, jvalue val, int long_form) { jint low; jint high; switch ( ty ) { case HPROF_ARRAY_OBJECT: check_printf("0x%08x", val.i); break; case HPROF_NORMAL_OBJECT: check_printf("0x%08x", val.i); break; case HPROF_BOOLEAN: check_printf("0x%02x", val.b); break; case HPROF_CHAR: if ( long_form ) { if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) { check_printf("0x%04x", val.s); } else { check_printf("0x%04x(%c)", val.s, val.s); } } else { if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) { check_printf("\\u%04x", val.s); } else { check_printf("%c", val.s); } } break; case HPROF_FLOAT: low = jlong_low(val.j); check_printf("0x%08x(%f)", low, (double)val.f); break; case HPROF_DOUBLE: high = jlong_high(val.j); low = jlong_low(val.j); check_printf("0x%08x%08x(%f)", high, low, val.d); break; case HPROF_BYTE: check_printf("0x%02x", val.b); break; case HPROF_SHORT: check_printf("0x%04x", val.s); break; case HPROF_INT: check_printf("0x%08x", val.i); break; case HPROF_LONG: high = jlong_high(val.j); low = jlong_low(val.j); check_printf("0x%08x%08x", high, low); break; } }
static void list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { SiteKey *pkey; jlong n_alloced_instances; jlong n_alloced_bytes; jlong n_live_instances; jlong n_live_bytes; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len==sizeof(SiteKey)); pkey = (SiteKey*)key_ptr; if ( info_ptr != NULL ) { SiteInfo *info; info = (SiteInfo *)info_ptr; n_alloced_instances = info->n_alloced_instances; n_alloced_bytes = info->n_alloced_bytes; n_live_instances = info->n_live_instances; n_live_bytes = info->n_live_bytes; } else { n_alloced_instances = 0; n_alloced_bytes = 0; n_live_instances = 0; n_live_bytes = 0; } debug_message( "Site 0x%08x: class=0x%08x, trace=0x%08x, " "Ninst=(%d,%d), Nbytes=(%d,%d), " "Nlive=(%d,%d), NliveBytes=(%d,%d)\n", i, pkey->cnum, pkey->trace_index, jlong_high(n_alloced_instances), jlong_low(n_alloced_instances), jlong_high(n_alloced_bytes), jlong_low(n_alloced_bytes), jlong_high(n_live_instances), jlong_low(n_live_instances), jlong_high(n_live_bytes), jlong_low(n_live_bytes)); }
/* Dump information about a field and what ref data we had on it */ static void dump_field(FieldInfo *fields, jvalue *fvalues, int n_fields, jint index, jvalue value, jvmtiPrimitiveType primType) { ClassIndex cnum; StringIndex name; StringIndex sig; cnum = fields[index].cnum; name = fields[index].name_index; sig = fields[index].sig_index; debug_message("[%d] %s \"%s\" \"%s\"", index, cnum!=0?string_get(class_get_signature(cnum)):"?", name!=0?string_get(name):"?", sig!=0?string_get(sig):"?"); if ( fields[index].primType!=0 || fields[index].primType!=primType ) { debug_message(" (primType=%d(%c)", fields[index].primType, primTypeToSigChar(fields[index].primType)); if ( primType != fields[index].primType ) { debug_message(", got %d(%c)", primType, primTypeToSigChar(primType)); } debug_message(")"); } else { debug_message("(ty=OBJ)"); } if ( value.j != (jlong)0 || fvalues[index].j != (jlong)0 ) { debug_message(" val=[0x%08x,0x%08x] or [0x%08x,0x%08x]", jlong_high(value.j), jlong_low(value.j), jlong_high(fvalues[index].j), jlong_low(fvalues[index].j)); } debug_message("\n"); }
/* Check all the heap tags in a heap dump */ static int check_tags(unsigned char *pstart, int nbytes) { unsigned char *p; int nrecord; struct LookupTable *utab; UmapInfo umap; check_printf("\nCHECK TAGS: starting\n"); utab = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo)); /* Walk the tags, assumes UTF8 tags are defined before used */ p = pstart; nrecord = 0; while ( p < (pstart+nbytes) ) { unsigned tag; unsigned size; int nheap_records; int npos; char *label; HprofId id, nm, sg, so, gr, gn; int i, li, num_elements; HprofType ty; SerialNumber trace_serial_num; SerialNumber thread_serial_num; SerialNumber class_serial_num; unsigned flags; unsigned depth; float cutoff; unsigned temp; jint nblive; jint nilive; jlong tbytes; jlong tinsts; jint total_samples; jint trace_count; nrecord++; /*LINTED*/ npos = (int)(p - pstart); tag = read_u1(&p); (void)read_u4(&p); /* microsecs */ size = read_u4(&p); #define CASE_TAG(name) case name: label = #name; switch ( tag ) { CASE_TAG(HPROF_UTF8) CHECK_FOR_ERROR(size>=(int)sizeof(HprofId)); id = read_id(&p); check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"", nrecord, npos, label, size, id); num_elements = size-(int)sizeof(HprofId); check_raw(p, num_elements); check_printf("\"\n"); /* Create entry in umap */ umap.str = HPROF_MALLOC(num_elements+1); (void)strncpy(umap.str, (char*)p, (size_t)num_elements); umap.str[num_elements] = 0; (void)table_create_entry(utab, &id, sizeof(id), &umap); p += num_elements; break; CASE_TAG(HPROF_LOAD_CLASS) CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId)); class_serial_num = read_u4(&p); CHECK_CLASS_SERIAL_NO(class_serial_num); id = read_id(&p); trace_serial_num = read_u4(&p); CHECK_TRACE_SERIAL_NO(trace_serial_num); nm = read_id(&p); check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u," " id=0x%x, trace_serial_num=%u, name_id=0x%x\n", nrecord, npos, label, size, class_serial_num, id, trace_serial_num, nm); break; CASE_TAG(HPROF_UNLOAD_CLASS) CHECK_FOR_ERROR(size==4); class_serial_num = read_u4(&p); CHECK_CLASS_SERIAL_NO(class_serial_num); check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n", nrecord, npos, label, size, class_serial_num); break; CASE_TAG(HPROF_FRAME) CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId)); id = read_id(&p); nm = read_id(&p); sg = read_id(&p); so = read_id(&p); class_serial_num = read_u4(&p); CHECK_CLASS_SERIAL_NO(class_serial_num); li = read_u4(&p); check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size); check_print_utf8(utab, "id=", id); check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x," " class_serial_num=%u, lineno=%d\n", nm, sg, so, class_serial_num, li); break; CASE_TAG(HPROF_TRACE) CHECK_FOR_ERROR(size>=3*4); trace_serial_num = read_u4(&p); CHECK_TRACE_SERIAL_NO(trace_serial_num); thread_serial_num = read_u4(&p); /* Can be 0 */ num_elements = read_u4(&p); check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u," " thread_serial_num=%u, nelems=%d [", nrecord, npos, label, size, trace_serial_num, thread_serial_num, num_elements); for(i=0; i< num_elements; i++) { check_printf("0x%x,", read_id(&p)); } check_printf("]\n"); break; CASE_TAG(HPROF_ALLOC_SITES) CHECK_FOR_ERROR(size>=2+4*4+2*8); flags = read_u2(&p); temp = read_u4(&p); cutoff = *((float*)&temp); nblive = read_u4(&p); nilive = read_u4(&p); tbytes = read_u8(&p); tinsts = read_u8(&p); num_elements = read_u4(&p); check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g," " nblive=%d, nilive=%d, tbytes=(%d,%d)," " tinsts=(%d,%d), num_elements=%d\n", nrecord, npos, label, size, flags, cutoff, nblive, nilive, jlong_high(tbytes), jlong_low(tbytes), jlong_high(tinsts), jlong_low(tinsts), num_elements); for(i=0; i< num_elements; i++) { ty = read_u1(&p); class_serial_num = read_u4(&p); CHECK_CLASS_SERIAL_NO(class_serial_num); trace_serial_num = read_u4(&p); CHECK_TRACE_SERIAL_NO(trace_serial_num); nblive = read_u4(&p); nilive = read_u4(&p); tbytes = read_u4(&p); tinsts = read_u4(&p); check_printf("\t %d: ty=%d, class_serial_num=%u," " trace_serial_num=%u, nblive=%d, nilive=%d," " tbytes=%d, tinsts=%d\n", i, ty, class_serial_num, trace_serial_num, nblive, nilive, (jint)tbytes, (jint)tinsts); } break; CASE_TAG(HPROF_HEAP_SUMMARY) CHECK_FOR_ERROR(size==2*4+2*8); nblive = read_u4(&p); nilive = read_u4(&p); tbytes = read_u8(&p); tinsts = read_u8(&p); check_printf("#%d@%d: %s, sz=%d," " nblive=%d, nilive=%d, tbytes=(%d,%d)," " tinsts=(%d,%d)\n", nrecord, npos, label, size, nblive, nilive, jlong_high(tbytes), jlong_low(tbytes), jlong_high(tinsts), jlong_low(tinsts)); break; CASE_TAG(HPROF_START_THREAD) CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId)); thread_serial_num = read_u4(&p); CHECK_THREAD_SERIAL_NO(thread_serial_num); id = read_id(&p); trace_serial_num = read_u4(&p); CHECK_TRACE_SERIAL_NO(trace_serial_num); nm = read_id(&p); gr = read_id(&p); gn = read_id(&p); check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u," " id=0x%x, trace_serial_num=%u, ", nrecord, npos, label, size, thread_serial_num, id, trace_serial_num); check_print_utf8(utab, "nm=", id); check_printf(" trace_serial_num=%u, nm=0x%x," " gr=0x%x, gn=0x%x\n", trace_serial_num, nm, gr, gn); break; CASE_TAG(HPROF_END_THREAD) CHECK_FOR_ERROR(size==4); thread_serial_num = read_u4(&p); CHECK_THREAD_SERIAL_NO(thread_serial_num); check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n", nrecord, npos, label, size, thread_serial_num); break; CASE_TAG(HPROF_HEAP_DUMP) check_printf("#%d@%d: BEGIN: %s, sz=%d\n", nrecord, npos, label, size); nheap_records = check_heap_tags(utab, p, size); check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n", nrecord, npos, label, size, nheap_records); p += size; break; CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */ check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n", nrecord, npos, label, size); nheap_records = check_heap_tags(utab, p, size); check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n", nrecord, npos, label, size, nheap_records); p += size; break; CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */ check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n", nrecord, npos, label, size); break; CASE_TAG(HPROF_CPU_SAMPLES) CHECK_FOR_ERROR(size>=2*4); total_samples = read_u4(&p); trace_count = read_u4(&p); check_printf("#%d@%d: %s, sz=%d, total_samples=%d," " trace_count=%d\n", nrecord, npos, label, size, total_samples, trace_count); for(i=0; i< trace_count; i++) { num_elements = read_u4(&p); trace_serial_num = read_u4(&p); CHECK_TRACE_SERIAL_NO(trace_serial_num); check_printf("\t %d: samples=%d, trace_serial_num=%u\n", trace_serial_num, num_elements); } break; CASE_TAG(HPROF_CONTROL_SETTINGS) CHECK_FOR_ERROR(size==4+2); flags = read_u4(&p); depth = read_u2(&p); check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n", nrecord, npos, label, size, flags, depth); break; default: label = "UNKNOWN"; check_printf("#%d@%d: %s, sz=%d\n", nrecord, npos, label, size); HPROF_ERROR(JNI_TRUE, "unknown record type"); p += size; break; } CHECK_FOR_ERROR(p<=(pstart+nbytes)); } check_flush(); CHECK_FOR_ERROR(p==(pstart+nbytes)); table_cleanup(utab, &utab_cleanup, NULL); return nrecord; }
/* the callback thread */ static void hprof_callback(void *p) { while (hprof_is_on) { jint length; jint seq_num; unsigned char tag; tag = recv_u1(); if (tag == HPROF_CMD_EOF) { /* the cmd socket has closed so the listener thread is done */ break; } seq_num = recv_u4(); length = recv_u4(); switch (tag) { case HPROF_CMD_GC: CALL(RunGC)(); break; case HPROF_CMD_DUMP_HEAP: { hprof_get_heap_dump(); break; } case HPROF_CMD_ALLOC_SITES: { unsigned short flags = recv_u2(); unsigned int i_tmp = recv_u4(); float ratio = *(float *)(&i_tmp); hprof_output_sites(flags, ratio); break; } case HPROF_CMD_HEAP_SUMMARY: { CALL(RawMonitorEnter)(data_access_lock); hprof_write_header(HPROF_HEAP_SUMMARY, 24); hprof_write_u4(total_live_bytes); hprof_write_u4(total_live_instances); hprof_write_u4(jlong_high(total_alloced_bytes)); hprof_write_u4(jlong_low(total_alloced_bytes)); hprof_write_u4(jlong_high(total_alloced_instances)); hprof_write_u4(jlong_low(total_alloced_instances)); CALL(RawMonitorExit)(data_access_lock); break; } case HPROF_CMD_EXIT: hprof_is_on = FALSE; fprintf(stderr, "HPROF: received exit event, exiting ...\n"); CALL(ProfilerExit)((jint)0); case HPROF_CMD_DUMP_TRACES: CALL(RawMonitorEnter)(data_access_lock); hprof_output_unmarked_traces(); CALL(RawMonitorExit)(data_access_lock); break; case HPROF_CMD_CPU_SAMPLES: { unsigned short flags = recv_u2(); unsigned int i_tmp = recv_u4(); float ratio = *(float *)(&i_tmp); hprof_output_trace_cost(ratio, CPU_SAMPLES_RECORD_NAME); break; } case HPROF_CMD_CONTROL: { unsigned short cmd = recv_u2(); if (cmd == 0x0001) { CALL(EnableEvent)(JVMPI_EVENT_OBJ_ALLOC, NULL); } else if (cmd == 0x0002) { CALL(DisableEvent)(JVMPI_EVENT_OBJ_ALLOC, NULL); } else if (cmd == 0x0003) { hprof_objmap_t *thread_id = recv_id(); hprof_cpu_sample_on(thread_id); } else if (cmd == 0x0004) { hprof_objmap_t *thread_id = recv_id(); hprof_cpu_sample_off(thread_id); } else if (cmd == 0x0005) { CALL(RawMonitorEnter)(data_access_lock); hprof_clear_trace_cost(); CALL(RawMonitorExit)(data_access_lock); } else if (cmd == 0x0006) { CALL(RawMonitorEnter)(data_access_lock); hprof_clear_site_table(); CALL(RawMonitorExit)(data_access_lock); } else if (cmd == 0x0007) { max_trace_depth = recv_u2(); } break; } default: if (hprof_is_on) { hprof_is_on = FALSE; fprintf(stderr, "HPROF ERROR : failed to recognize cmd %d, exiting..\n", (int)tag); } CALL(ProfilerExit)((jint)1); } CALL(RawMonitorEnter)(data_access_lock); hprof_flush(); CALL(RawMonitorExit)(data_access_lock); } }