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 + -
显示快捷键?