hprof_reference.c
来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 812 行 · 第 1/2 页
C
812 行
/* * @(#)hprof_reference.c 1.42 05/11/17 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. *//* Object references table (used in hprof_object.c). *//* * This table is used by the object table to store object reference * and primitive data information obtained from iterations over the * heap (see hprof_site.c). * * Most of these table entries have no Key, but the key is used to store * the primitive array and primitive field jvalue. None of these entries * are ever looked up, there will be no hash table, use of the * LookupTable was just an easy way to handle a unbounded table of * entries. The object table (see hprof_object.c) will completely * free this reference table after each heap dump or after processing the * references and primitive data. * * The hprof format required this accumulation of all heap iteration * references and primitive data from objects in order to compose an * hprof records for it. * * This file contains detailed understandings of how an hprof CLASS * and INSTANCE dump is constructed, most of this is derived from the * original hprof code, but some has been derived by reading the HAT * code that accepts this format. * */#include "hprof.h"/* The flavor of data being saved in the RefInfo */enum { INFO_OBJECT_REF_DATA = 1, INFO_PRIM_FIELD_DATA = 2, INFO_PRIM_ARRAY_DATA = 3};/* Reference information, object reference or primitive data information */typedef struct RefInfo { ObjectIndex object_index; /* If an object reference, the referree index */ jint index; /* If array or field, array or field index */ jint length; /* If array the element count, if not -1 */ RefIndex next; /* The next table element */ unsigned flavor : 8; /* INFO_*, flavor of RefInfo */ unsigned refKind : 8; /* The kind of reference */ unsigned primType : 8; /* If primitive data involved, it's type */} RefInfo;/* Private internal functions. *//* Get the RefInfo structure from an entry */static RefInfo *get_info(RefIndex index){ RefInfo *info; info = (RefInfo*)table_get_info(gdata->reference_table, index); return info;}/* Get a jvalue that was stored as the key. */static jvalueget_key_value(RefIndex index){ void *key; int len; jvalue value; static jvalue empty_value; key = NULL; table_get_key(gdata->reference_table, index, &key, &len); HPROF_ASSERT(key!=NULL); HPROF_ASSERT(len==(int)sizeof(jvalue)); if ( key != NULL ) { (void)memcpy(&value, key, (int)sizeof(jvalue)); } else { value = empty_value; } return value;}/* Get size of a primitive type */static jintget_prim_size(jvmtiPrimitiveType primType){ jint size; switch ( primType ) { case JVMTI_PRIMITIVE_TYPE_BOOLEAN: size = (jint)sizeof(jboolean); break; case JVMTI_PRIMITIVE_TYPE_BYTE: size = (jint)sizeof(jbyte); break; case JVMTI_PRIMITIVE_TYPE_CHAR: size = (jint)sizeof(jchar); break; case JVMTI_PRIMITIVE_TYPE_SHORT: size = (jint)sizeof(jshort); break; case JVMTI_PRIMITIVE_TYPE_INT: size = (jint)sizeof(jint); break; case JVMTI_PRIMITIVE_TYPE_FLOAT: size = (jint)sizeof(jfloat); break; case JVMTI_PRIMITIVE_TYPE_LONG: size = (jint)sizeof(jlong); break; case JVMTI_PRIMITIVE_TYPE_DOUBLE: size = (jint)sizeof(jdouble); break; default: HPROF_ASSERT(0); size = 1; break; } return size;}/* Get a void* elements array that was stored as the key. */static void *get_key_elements(RefIndex index, jvmtiPrimitiveType primType, jint *nelements, jint *nbytes){ void *key; jint byteLen; HPROF_ASSERT(nelements!=NULL); HPROF_ASSERT(nbytes!=NULL); table_get_key(gdata->reference_table, index, &key, &byteLen); HPROF_ASSERT(byteLen>=0); HPROF_ASSERT(byteLen!=0?key!=NULL:key==NULL); *nbytes = byteLen; *nelements = byteLen / get_prim_size(primType); return key;}/* Dump a RefInfo* structure */static voiddump_ref_info(RefInfo *info){ debug_message("[%d]: flavor=%d" ", refKind=%d" ", primType=%d" ", object_index=0x%x" ", length=%d" ", next=0x%x" "\n", info->index, info->flavor, info->refKind, info->primType, info->object_index, info->length, info->next);}/* Dump a RefIndex list */static voiddump_ref_list(RefIndex list){ RefInfo *info; RefIndex index; debug_message("\nFOLLOW REFERENCES RETURNED:\n"); index = list; while ( index != 0 ) { info = get_info(index); dump_ref_info(info); index = info->next; }}/* Dump information about a field and what ref data we had on it */static voiddump_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");}/* Dump all the fields of interest */static voiddump_fields(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields){ int i; debug_message("\nHPROF LIST OF ALL FIELDS:\n"); for ( i = 0 ; i < n_fields ; i++ ) { if ( fields[i].name_index != 0 ) { dump_field(fields, fvalues, n_fields, i, fvalues[i], fields[i].primType); } } dump_ref_list(list);}/* Verify field data */static voidverify_field(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields, jint index, jvalue value, jvmtiPrimitiveType primType){ HPROF_ASSERT(fvalues != NULL); HPROF_ASSERT(n_fields > 0); HPROF_ASSERT(index < n_fields); HPROF_ASSERT(index >= 0 ); if ( primType!=fields[index].primType ) { dump_fields(list, fields, fvalues, n_fields); debug_message("\nPROBLEM WITH:\n"); dump_field(fields, fvalues, n_fields, index, value, primType); debug_message("\n"); HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data"); } if ( primType == JVMTI_PRIMITIVE_TYPE_BOOLEAN && ( value.b != 1 && value.b != 0 ) ) { dump_fields(list, fields, fvalues, n_fields); debug_message("\nPROBLEM WITH:\n"); dump_field(fields, fvalues, n_fields, index, value, primType); debug_message("\n"); HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data"); }}/* Fill in a field value, making sure the index is safe */static voidfill_in_field_value(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields, jint index, jvalue value, jvmtiPrimitiveType primType){ HPROF_ASSERT(fvalues != NULL); HPROF_ASSERT(n_fields > 0); HPROF_ASSERT(index < n_fields); HPROF_ASSERT(index >= 0 ); HPROF_ASSERT(fvalues[index].j==(jlong)0); verify_field(list, fields, fvalues, n_fields, index, value, primType); if (index >= 0 && index < n_fields) { fvalues[index] = value; }}/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */static voiddump_class_and_supers(JNIEnv *env, ObjectIndex object_index, RefIndex list){ SiteIndex site_index; SerialNumber trace_serial_num; RefIndex index; ClassIndex super_cnum; ObjectIndex super_index; LoaderIndex loader_index; ObjectIndex signers_index; ObjectIndex domain_index; FieldInfo *fields; jvalue *fvalues; jint n_fields; jboolean skip_fields; jint n_fields_set; jlong size; ClassIndex cnum; char *sig; ObjectKind kind; TraceIndex trace_index; Stack *cpool_values; ConstantPoolValue *cpool; jint cpool_count; HPROF_ASSERT(object_index!=0); kind = object_get_kind(object_index); if ( kind != OBJECT_CLASS ) { return; } site_index = object_get_site(object_index); HPROF_ASSERT(site_index!=0); cnum = site_get_class_index(site_index); HPROF_ASSERT(cnum!=0); if ( class_get_status(cnum) & CLASS_DUMPED ) { return; } class_add_status(cnum, CLASS_DUMPED); size = (jlong)object_get_size(object_index); super_index = 0; super_cnum = class_get_super(cnum); if ( super_cnum != 0 ) { super_index = class_get_object_index(super_cnum); if ( super_index != 0 ) { dump_class_and_supers(env, super_index, object_get_references(super_index)); } } trace_index = site_get_trace_index(site_index); HPROF_ASSERT(trace_index!=0); trace_serial_num = trace_get_serial_number(trace_index); sig = string_get(class_get_signature(cnum)); loader_index = class_get_loader(cnum); signers_index = 0; domain_index = 0; /* Get field information */ n_fields = 0; skip_fields = JNI_FALSE; n_fields_set = 0; fields = NULL; fvalues = NULL; if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) { /* Problems getting all the fields, can't trust field index values */ skip_fields = JNI_TRUE; /* Class with no references at all? (ok to be unprepared if list==0?) */ if ( list != 0 ) { /* It is assumed that the reason why we didn't get the fields * was because the class is not prepared. */ if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) { dump_ref_list(list); debug_message("Unprepared class with references: %s\n", sig); } HPROF_ERROR(JNI_FALSE, "Trouble with unprepared classes"); } /* Why would an unprepared class contain references? */ } if ( n_fields > 0 ) { fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue)); (void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue)); } /* We use a Stack just because it will automatically expand as needed */ cpool_values = stack_init(16, 16, sizeof(ConstantPoolValue)); cpool = NULL; cpool_count = 0; index = list; while ( index != 0 ) { RefInfo *info; jvalue ovalue; static jvalue empty_value; info = get_info(index); switch ( info->flavor ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?