/* Primitive array data callback for FollowReferences */
static jint JNICALL 
cbPrimArrayData(jlong class_tag, jlong size, jlong* tag_ptr, 
         jint element_count, jvmtiPrimitiveType element_type, 
         const void* elements, void* user_data)
{
    ObjectIndex   object_index;
    RefIndex      ref_index;
    RefIndex      prev_ref_index;

    HPROF_ASSERT(tag_ptr!=NULL);
    HPROF_ASSERT(class_tag!=(jlong)0);
    HPROF_ASSERT((*tag_ptr)!=(jlong)0);
    if ( class_tag == (jlong)0 || (*tag_ptr) == (jlong)0 ) {
        /* We can't do anything with a class_tag==0, just skip it */
        return JVMTI_VISIT_OBJECTS;
    }
   
    /* Assume object has been tagged, get object index */
    object_index = tag_extract((*tag_ptr));

    /* Save string data */
    prev_ref_index = object_get_references(object_index);
    ref_index = reference_prim_array(prev_ref_index,
                  element_type, elements, element_count);
    object_set_references(object_index, ref_index);

    return JVMTI_VISIT_OBJECTS;
}
Exemple #2
0
/* JVMTI callback function. */
static jvmtiIterationControl JNICALL
reference_object(jvmtiObjectReferenceKind reference_kind, 
		jlong class_tag, jlong size, jlong* tag_ptr, 
		jlong referrer_tag, jint referrer_index, void *user_data)
{

   /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
    *   are allowed here (see the JVMTI Spec).
    */

    RefIndex      ref_index;
    RefIndex      prev_ref_index;
    ObjectIndex   referrer_object_index;
    ObjectIndex   object_index;
    jlong         object_tag;

    HPROF_ASSERT(tag_ptr!=NULL);
    HPROF_ASSERT(referrer_tag!=(jlong)0);
    
    if ( referrer_tag != (jlong)0 ) {
	referrer_object_index = tag_extract(referrer_tag);
    } else {
        return JVMTI_ITERATION_CONTINUE;
    }
    
    object_tag = *tag_ptr;
    if ( object_tag != (jlong)0 ) {
        object_index = tag_extract(object_tag);
    } else {
        SiteIndex site_index;
	
        site_index = site_find_or_create(find_cnum(class_tag), 
			gdata->system_trace_index);
	object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM,
				gdata->system_thread_serial_num);
	object_tag = tag_create(object_index);
	*tag_ptr   = object_tag;
    }

    /* Save reference information */
    prev_ref_index = object_get_references(referrer_object_index);
    ref_index = reference_new(prev_ref_index, reference_kind,
		    class_tag, size, object_tag, referrer_index);
    object_set_references(referrer_object_index, ref_index);
    
    return JVMTI_ITERATION_CONTINUE;
}
/* Primitive field data callback for FollowReferences */
static jint JNICALL 
cbPrimFieldData(jvmtiHeapReferenceKind reference_kind, 
         const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, 
         jlong* tag_ptr, jvalue value, jvmtiPrimitiveType value_type, 
         void* user_data)
{
    ObjectIndex   object_index;
    jint          field_index;
    RefIndex      ref_index;
    RefIndex      prev_ref_index;

    HPROF_ASSERT(tag_ptr!=NULL);
    HPROF_ASSERT(class_tag!=(jlong)0);
    HPROF_ASSERT((*tag_ptr)!=(jlong)0);
    if ( class_tag == (jlong)0 || (*tag_ptr) == (jlong)0 ) {
        /* We can't do anything with a class_tag==0, just skip it */
        return JVMTI_VISIT_OBJECTS;
    }

    /* If the field is 0, just skip it, we assume 0 */
    if ( value.j == (jlong)0 ) {
        return JVMTI_VISIT_OBJECTS;
    }

    /* Get field index */
    field_index = reference_info->field.index;
   
    /* We assume the object was tagged */
    object_index = tag_extract((*tag_ptr));
    
    /* Save primitive field data */
    prev_ref_index = object_get_references(object_index);
    ref_index = reference_prim_field(prev_ref_index, reference_kind,
                  value_type, value, field_index);
    object_set_references(object_index, ref_index);

    return JVMTI_VISIT_OBJECTS;
}
/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */
static void
dump_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 ) {
            case INFO_OBJECT_REF_DATA:
                switch ( info->refKind ) {
                    case JVMTI_HEAP_REFERENCE_FIELD:
                    case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
                        /* Should never be seen on a class dump */
                        HPROF_ASSERT(0);
                        break;
                    case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
			if ( skip_fields == JNI_TRUE ) {
			    break;
			}
                        ovalue   = empty_value;
                        ovalue.i = info->object_index;
                        fill_in_field_value(list, fields, fvalues, n_fields, 
                                        info->index, ovalue, 0);
                        n_fields_set++;
                        HPROF_ASSERT(n_fields_set <= n_fields);
                        break;
                    case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: {
                        ConstantPoolValue cpv;
                        ObjectIndex       cp_object_index;
                        SiteIndex         cp_site_index;
                        ClassIndex        cp_cnum;
                        
                        cp_object_index = info->object_index;
                        HPROF_ASSERT(cp_object_index!=0);
                        cp_site_index = object_get_site(cp_object_index);
                        HPROF_ASSERT(cp_site_index!=0);
                        cp_cnum = site_get_class_index(cp_site_index);
                        cpv.constant_pool_index = info->index;
                        cpv.sig_index = class_get_signature(cp_cnum); 
                        cpv.value.i = cp_object_index;
                        stack_push(cpool_values, (void*)&cpv);
                        cpool_count++;
                        break;
                        }
                    case JVMTI_HEAP_REFERENCE_SIGNERS:
                        signers_index = info->object_index;
                        break;
                    case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
                        domain_index = info->object_index;
                        break;
                    case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
                    case JVMTI_HEAP_REFERENCE_INTERFACE:
                    default:
                        /* Ignore, not needed */
                        break;
                }
                break;
            case INFO_PRIM_FIELD_DATA:
		if ( skip_fields == JNI_TRUE ) {
		    break;
		}
                HPROF_ASSERT(info->primType!=0);
                HPROF_ASSERT(info->length==-1);
                HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_STATIC_FIELD);
                ovalue = get_key_value(index);
                fill_in_field_value(list, fields, fvalues, n_fields, 
                                    info->index, ovalue, info->primType);
                n_fields_set++;
                HPROF_ASSERT(n_fields_set <= n_fields);
                break;
            case INFO_PRIM_ARRAY_DATA:
            default:
                /* Should never see these */
                HPROF_ASSERT(0);
                break;
        }

        index = info->next;
    }

    /* Get constant pool data if we have any */
    HPROF_ASSERT(cpool_count==stack_depth(cpool_values));
    if ( cpool_count > 0 ) {
        cpool = (ConstantPoolValue*)stack_element(cpool_values, 0);
    }
    io_heap_class_dump(cnum, sig, object_index, trace_serial_num,
            super_index, 
            loader_object_index(env, loader_index), 
            signers_index, domain_index,
            (jint)size, cpool_count, cpool, n_fields, fields, fvalues);

    stack_term(cpool_values);
    if ( fvalues != NULL ) {
        HPROF_FREE(fvalues);
    }
}
/* Store away plain object reference information */
static jint
objectReference(jvmtiHeapReferenceKind reference_kind, 
                  const jvmtiHeapReferenceInfo* reference_info, 
                  jlong class_tag, jlong size, jlong* tag_ptr, 
                  jlong* referrer_tag_ptr, jint length)
{
    ObjectIndex   object_index;
    jint          reference_index;
    RefIndex      ref_index;
    RefIndex      prev_ref_index;
    ObjectIndex   referrer_object_index;
    jlong         object_tag;

    HPROF_ASSERT(tag_ptr!=NULL);
    HPROF_ASSERT(class_tag!=(jlong)0);
    HPROF_ASSERT(referrer_tag_ptr!=NULL);
    HPROF_ASSERT((*referrer_tag_ptr)!=(jlong)0);
    if ( class_tag == (jlong)0 || (*referrer_tag_ptr) == (jlong)0 ) {
        /* We can't do anything with a class_tag==0, just skip it */
        return JVMTI_VISIT_OBJECTS;
    }
   
    switch ( reference_kind ) {
        default:
            /* Currently we don't need these */
            return JVMTI_VISIT_OBJECTS;
        case JVMTI_HEAP_REFERENCE_FIELD:
        case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
            reference_index = reference_info->field.index;
            break;
        case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
            reference_index = reference_info->array.index;
            break;
        case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
            reference_index = reference_info->constant_pool.index;
            break;
        case JVMTI_HEAP_REFERENCE_SIGNERS:
        case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
        case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
        case JVMTI_HEAP_REFERENCE_INTERFACE:
            reference_index = 0;
            break;
    }
   
    /* We assume the referrer is tagged */
    referrer_object_index = tag_extract((*referrer_tag_ptr));
   
    /* Now check the referree */
    object_tag = *tag_ptr;
    if ( object_tag != (jlong)0 ) {
        object_index = tag_extract(object_tag);
    } else {
        /* Create and set the tag. */
        object_tag = make_new_tag(class_tag, size, gdata->system_trace_index,
                                  gdata->unknown_thread_serial_num, 
                                  &object_index, NULL);
        *tag_ptr   = object_tag;
    }
    HPROF_ASSERT(object_index!=0);

    /* Save reference information */
    prev_ref_index = object_get_references(referrer_object_index);
    ref_index = reference_obj(prev_ref_index, reference_kind,
                    object_index, reference_index, length);
    object_set_references(referrer_object_index, ref_index);

    return JVMTI_VISIT_OBJECTS;
}
Exemple #6
0
/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */
static void
dump_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;
    jlong        size;
    ClassIndex   cnum;
    char        *sig;
    ObjectKind   kind;
    TraceIndex   trace_index;
    Stack       *cpool_values;
    ConstantPoolValue *cpool;
    jint         cpool_count;
    jboolean     skip_fields;

    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));
    
    n_fields     = 0;
    fields       = NULL;
    fvalues      = NULL;
    skip_fields  = JNI_TRUE;
    if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 0 ) {
        if ( n_fields > 0 ) {
            skip_fields  = JNI_FALSE;
	    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;
    
    loader_index     = class_get_loader(cnum);
    signers_index    = 0;
    domain_index     = 0;

    index      = list;
    while ( index != 0 ) {
	RefInfo    *info;

	info = get_info(index);

	/* Process reference objects, many not used right now. */
	switch ( info->kind ) {
	    case JVMTI_REFERENCE_STATIC_FIELD:
		/* If the class_tag is 0, it is possible for 
		 *    info->element_index to be >= n_fields
		 *    and when this happens we just skip this field ref
		 *    for now. We probably have a java.lang.Object class
		 *    with n_fields==0, which is probably the wrong class.
		 */
		if (info->class_tag == (jlong)0 || skip_fields == JNI_TRUE ) {
		    break;
		}
		HPROF_ASSERT(info->element_index < n_fields);
		if (info->element_index < n_fields) {
	            ObjectIndex field_object_index;
		
		    /* Field index is referrer_index from referrer_tag */
		    field_object_index = tag_to_object_index(info->object_tag);
		    fvalues[info->element_index].i = field_object_index;
		}
		break;
	    case JVMTI_REFERENCE_CONSTANT_POOL: {
		ConstantPoolValue cpv;
		ObjectIndex       cp_object_index;
		SiteIndex         cp_site_index;
		ClassIndex        cp_cnum;
	        
		cp_object_index = tag_to_object_index(info->object_tag);
                HPROF_ASSERT(cp_object_index!=0);
                cp_site_index = object_get_site(cp_object_index);
                HPROF_ASSERT(cp_site_index!=0);
                cp_cnum = site_get_class_index(cp_site_index);
		cpv.constant_pool_index = info->element_index;
		cpv.sig_index = class_get_signature(cp_cnum); 
		cpv.value.i = cp_object_index;
		stack_push(cpool_values, (void*)&cpv);
		cpool_count++;
		break;
		}
	    default:
		break;
	}
	index = info->next;
    }

    /* FIXUP: Fill rest of static primitive fields? If requested? */
    /*   Use: value = getStaticFieldValue(env, klass, field, field_sig); ? */

    HPROF_ASSERT(cpool_count==stack_depth(cpool_values));
    if ( cpool_count > 0 ) {
	cpool = (ConstantPoolValue*)stack_element(cpool_values, 0);
    }
    io_heap_class_dump(cnum, sig, object_index, trace_serial_num,
	    super_index, loader_index, signers_index, domain_index,
	    (jint)size, cpool_count, cpool, n_fields, fields, fvalues);

    stack_term(cpool_values);
    if ( fvalues != NULL ) {
	HPROF_FREE(fvalues);
    }
}