alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (hprof_check.c)

This example Java source code file (hprof_check.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

case_heap, case_tag, check_for_error, check_trace_serial_no, cmapinfo, hprof_assert, hprof_error, hprofid, hproftype, lookuptable, null, serialnumber, umapinfo, unknown

The hprof_check.c Java example source code

/*
 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions 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 Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


/* Functionality for checking hprof format=b output. */

/* ONLY used with logflags=4. */

/* Verifies and write a verbose textual version of a format=b file.
 *   Textual output file is gdata->checkfilename, fd is gdata->check_fd.
 *   Buffer is in gdata too, see gdata->check* variables.
 *   Could probably be isolated to a separate library or utility.
 */

#include "hprof.h"

typedef TableIndex HprofId;

#include "hprof_b_spec.h"

static int type_size[ /*HprofType*/ ] =  HPROF_TYPE_SIZES;

/* For map from HPROF_UTF8 to a string */
typedef struct UmapInfo {
    char *str;
} UmapInfo;

/* Field information */
typedef struct Finfo {
    HprofId   id;
    HprofType ty;
} Finfo;

/* Class information map from class ID (ClassIndex) to class information */
typedef struct CmapInfo {
    int      max_finfo;
    int      n_finfo;
    Finfo   *finfo;
    int      inst_size;
    HprofId  sup;
} CmapInfo;

/* Read raw bytes from the file image, update the pointer */
static void
read_raw(unsigned char **pp, unsigned char *buf, int len)
{
    while ( len > 0 ) {
        *buf = **pp;
        buf++;
        (*pp)++;
        len--;
    }
}

/* Read various sized elements, properly converted from big to right endian.
 *    File will contain big endian format.
 */
static unsigned
read_u1(unsigned char **pp)
{
    unsigned char b;

    read_raw(pp, &b, 1);
    return b;
}
static unsigned
read_u2(unsigned char **pp)
{
    unsigned short s;

    read_raw(pp, (void*)&s, 2);
    return md_htons(s);
}
static unsigned
read_u4(unsigned char **pp)
{
    unsigned int u;

    read_raw(pp, (void*)&u, 4);
    return md_htonl(u);
}
static jlong
read_u8(unsigned char **pp)
{
    unsigned int high;
    unsigned int low;
    jlong        x;

    high = read_u4(pp);
    low  = read_u4(pp);
    x = high;
    x = (x << 32) | low;
    return x;
}
static HprofId
read_id(unsigned char **pp)
{
    return (HprofId)read_u4(pp);
}

/* System error routine */
static void
system_error(const char *system_call, int rc, int errnum)
{
    char buf[256];
    char details[256];

    details[0] = 0;
    if ( errnum != 0 ) {
        md_system_error(details, (int)sizeof(details));
    } else if ( rc >= 0 ) {
        (void)strcpy(details,"Only part of buffer processed");
    }
    if ( details[0] == 0 ) {
        (void)strcpy(details,"Unknown system error condition");
    }
    (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
                            system_call, details);
    HPROF_ERROR(JNI_TRUE, buf);
}

/* Write to a fd */
static void
system_write(int fd, void *buf, int len)
{
    int res;

    HPROF_ASSERT(fd>=0);
    res = md_write(fd, buf, len);
    if (res < 0 || res!=len) {
        system_error("write", res, errno);
    }
}

/* Flush check buffer */
static void
check_flush(void)
{
    if ( gdata->check_fd < 0 ) {
        return;
    }
    if (gdata->check_buffer_index) {
        system_write(gdata->check_fd, gdata->check_buffer, gdata->check_buffer_index);
        gdata->check_buffer_index = 0;
    }
}

/* Read out a given typed element */
static jvalue
read_val(unsigned char **pp, HprofType ty)
{
    jvalue        val;
    static jvalue empty_val;

    val = empty_val;
    switch ( ty ) {
        case 0:
        case HPROF_ARRAY_OBJECT:
        case HPROF_NORMAL_OBJECT:
            val.i = read_id(pp);
            break;
        case HPROF_BYTE:
        case HPROF_BOOLEAN:
            val.b = read_u1(pp);
            break;
        case HPROF_CHAR:
        case HPROF_SHORT:
            val.s = read_u2(pp);
            break;
        case HPROF_FLOAT:
        case HPROF_INT:
            val.i = read_u4(pp);
            break;
        case HPROF_DOUBLE:
        case HPROF_LONG:
            val.j = read_u8(pp);
            break;
        default:
            HPROF_ERROR(JNI_TRUE, "bad type number");
            break;
    }
    return val;
}

/* Move arbitrary byte stream into gdata->check_fd */
static void
check_raw(void *buf, int len)
{
    if ( gdata->check_fd < 0 ) {
        return;
    }

    if ( len <= 0 ) {
        return;
    }

    if (gdata->check_buffer_index + len > gdata->check_buffer_size) {
        check_flush();
        if (len > gdata->check_buffer_size) {
            system_write(gdata->check_fd, buf, len);
            return;
        }
    }
    (void)memcpy(gdata->check_buffer + gdata->check_buffer_index, buf, len);
    gdata->check_buffer_index += len;
}

/* Printf for gdata->check_fd */
static void
check_printf(char *fmt, ...)
{
    char    buf[1024];
    va_list args;

    if ( gdata->check_fd < 0 ) {
        return;
    }

    va_start(args, fmt);
    (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
    buf[sizeof(buf)-1] = 0;
    check_raw(buf, (int)strlen(buf));
    va_end(args);
}

/* 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;
    }
}

/* Printf of a string for gdata->check_fd */
static void
check_printf_str(char *str)
{
    int len;
    int i;

    if ( str == NULL ) {
        check_printf("<null>");
    }
    check_printf("\"");
    len = (int)strlen(str);
    for (i = 0; i < len; i++) {
        unsigned char c;
        c = str[i];
        if ( isprint(c) ) {
            check_printf("%c", c);
        } else {
            check_printf("\\x%02x", c);
        }
    }
    check_printf("\"");
}

/* Printf of a utf8 id for gdata->check_fd */
static void
check_print_utf8(struct LookupTable *utab, char *prefix, HprofId id)
{
    TableIndex uindex;

    if ( id == 0 ) {
        check_printf("%s0x%x", prefix, id);
    } else {
        uindex = table_find_entry(utab, &id, sizeof(id));
        if ( uindex == 0 ) {
            check_printf("%s0x%x", prefix, id);
        } else {
            UmapInfo *umap;

            umap = (UmapInfo*)table_get_info(utab, uindex);
            HPROF_ASSERT(umap!=NULL);
            HPROF_ASSERT(umap->str!=NULL);
            check_printf("%s0x%x->", prefix, id);
            check_printf_str(umap->str);
        }
    }
}

/* Add a instance field information to this cmap. */
static void
add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty)
{
   int i;

   HPROF_ASSERT(cmap!=NULL);
   i = cmap->n_finfo++;
   if ( i+1 >= cmap->max_finfo ) {
       int    osize;
       Finfo *new_finfo;

       osize            = cmap->max_finfo;
       cmap->max_finfo += 12;
       new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo));
       (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo));
       if ( i == 0 ) {
           cmap->finfo = new_finfo;
       } else {
           (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo));
           HPROF_FREE(cmap->finfo);
           cmap->finfo = new_finfo;
       }
   }
   cmap->finfo[i].id = id;
   cmap->finfo[i].ty = ty;
}

/* LookupTable callback for cmap entry cleanup */
static void
cmap_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
{
    CmapInfo *cmap = info;

    if ( cmap == NULL ) {
        return;
    }
    if ( cmap->finfo != NULL ) {
        HPROF_FREE(cmap->finfo);
        cmap->finfo = NULL;
    }
}

/* Case label for a switch on hprof heap dump elements */
#define CASE_HEAP(name) case name: label = #name;

/* Given the heap dump data and the utf8 map, check/write the heap dump. */
static int
check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
{
    int                 nrecords;
    unsigned char      *p;
    unsigned char      *psave;
    struct LookupTable *ctab;
    CmapInfo            cmap;
    char               *label;
    unsigned            tag;
    HprofType           ty;
    HprofId             id, id2, fr, sup;
    int                 num_elements;
    int                 num_bytes;
    SerialNumber        trace_serial_num;
    SerialNumber        thread_serial_num;
    int                 npos;
    int                 i;
    int                 inst_size;

    ctab     = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));

    /* First pass over heap records just fills in the CmapInfo table */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id  = read_id(&p);
                id2 = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                (void)memset((void*)&cmap, 0, sizeof(cmap));
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup      = read_id(&p);
                    ld       = read_id(&p);
                    si       = read_id(&p);
                    pr       = read_id(&p);
                    re1      = read_id(&p);
                    re2      = read_id(&p);
                    cmap.sup = sup;
                }
                inst_size = read_u4(&p);
                cmap.inst_size = inst_size;
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_u2(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_id(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    add_inst_field_to_cmap(&cmap, id, ty);
                }
                (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                p += num_bytes;
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                p += num_elements*(int)sizeof(HprofId);
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                p += type_size[ty]*num_elements;
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    /* Scan again once we have our cmap */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id = read_id(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
                        nrecords, npos, label, id, id2);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
                             " trace_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num,
                        trace_serial_num);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
                        nrecords, npos, label, id, trace_serial_num);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup = read_id(&p);
                    ld  = read_id(&p);
                    si  = read_id(&p);
                    pr  = read_id(&p);
                    re1 = read_id(&p);
                    re2 = read_id(&p);
                    check_printf("  su=0x%x, ld=0x%x, si=0x%x,"
                                 " pr=0x%x, re1=0x%x, re2=0x%x\n",
                        sup, ld, si, pr, re1, re2);
                }
                inst_size = read_u4(&p);
                check_printf("  instance_size=%d\n", inst_size);

                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    unsigned  cpi;
                    jvalue    val;

                    cpi = read_u2(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  constant_pool %d: cpi=%d, ty=%d, val=",
                                i, cpi, ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  static_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;
                    jvalue    val;

                    id  = read_id(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  static field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d, val=", ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  instance_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    check_printf("  instance_field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d\n", ty);
                }
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
                             " cid=0x%x, nbytes=%d\n",
                            nrecords, npos, label, id, trace_serial_num,
                            id2, num_bytes);
                /* This is a packed set of bytes for the instance fields */
                if ( num_bytes > 0 ) {
                    TableIndex cindex;
                    int        ifield;
                    CmapInfo  *map;

                    cindex = table_find_entry(ctab, &id2, sizeof(id2));
                    HPROF_ASSERT(cindex!=0);
                    map = (CmapInfo*)table_get_info(ctab, cindex);
                    HPROF_ASSERT(map!=NULL);
                    HPROF_ASSERT(num_bytes==map->inst_size);

                    psave  = p;
                    ifield = 0;

                    do {
                        for(i=0;i<map->n_finfo;i++) {
                            HprofType ty;
                            HprofId   id;
                            jvalue    val;

                            ty = map->finfo[i].ty;
                            id = map->finfo[i].id;
                            HPROF_ASSERT(ty!=0);
                            HPROF_ASSERT(id!=0);
                            val = read_val(&p, ty);
                            check_printf("  field %d: ", ifield);
                            check_print_utf8(utab, "id=", id);
                            check_printf(", ty=%d, val=", ty);
                            check_printf_val(ty, val, 1);
                            check_printf("\n");
                            ifield++;
                        }
                        id2    = map->sup;
                        map    = NULL;
                        cindex = 0;
                        if ( id2 != 0 ) {
                            cindex = table_find_entry(ctab, &id2, sizeof(id2));
                            HPROF_ASSERT(cindex!=0);
                            map = (CmapInfo*)table_get_info(ctab, cindex);
                            HPROF_ASSERT(map!=NULL);
                        }
                    } while ( map != NULL );
                    HPROF_ASSERT(num_bytes==(p-psave));
                }
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, id2);
                for(i=0; i<num_elements; i++) {
                    HprofId id;

                    id = read_id(&p);
                    check_printf("  [%d]: id=0x%x\n", i, id);
                }
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                psave = p;
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
                             "nelems=%d, ty=%d\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, ty);
                HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
                if ( num_elements > 0 ) {
                    int   count;
                    int   long_form;
                    int   max_count;
                    char *quote;

                    quote     = "";
                    long_form = 1;
                    max_count = 8;
                    count     = 0;
                    switch ( ty ) {
                        case HPROF_CHAR:
                            long_form = 0;
                            max_count = 72;
                            quote     = "\"";
                            /*FALLTHRU*/
                        case HPROF_INT:
                        case HPROF_DOUBLE:
                        case HPROF_LONG:
                        case HPROF_BYTE:
                        case HPROF_BOOLEAN:
                        case HPROF_SHORT:
                        case HPROF_FLOAT:
                            check_printf("  val=%s", quote);
                            for(i=0; i<num_elements; i++) {
                                jvalue val;

                                if ( i > 0 && count == 0 ) {
                                    check_printf("  %s", quote);
                                }
                                val = read_val(&p, ty);
                                check_printf_val(ty, val, long_form);
                                count += 1;
                                if ( count >= max_count ) {
                                    check_printf("\"\n");
                                    count = 0;
                                }
                            }
                            if ( count != 0 ) {
                                check_printf("%s\n", quote);
                            }
                            break;
                    }
                }
                HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    table_cleanup(ctab, &cmap_cleanup, NULL);

    return nrecords;
}

/* LookupTable cleanup callback for utab */
static void
utab_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
{
    UmapInfo *umap = info;

    if ( umap == NULL ) {
        return;
    }
    if ( umap->str != NULL ) {
        HPROF_FREE(umap->str);
        umap->str = NULL;
    }
}

/* 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;
}

/* Read the entire file into memory */
static void *
get_binary_file_image(char *filename, int *pnbytes)
{
    unsigned char *image;
    int            fd;
    jlong          nbytes;
    int            nread;

    *pnbytes = 0;
    fd = md_open_binary(filename);
    CHECK_FOR_ERROR(fd>=0);
    if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) {
        HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file");
    }
    CHECK_FOR_ERROR(((jint)nbytes)>512);
    if ( md_seek(fd, (jlong)0) != (jlong)0 ) {
        HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file");
    }
    image = HPROF_MALLOC(((jint)nbytes)+1);
    CHECK_FOR_ERROR(image!=NULL);

    /* Read the entire file image into memory */
    nread = md_read(fd, image, (jint)nbytes);
    if ( nread <= 0 ) {
        HPROF_ERROR(JNI_TRUE, "System read failed.");
    }
    CHECK_FOR_ERROR(((jint)nbytes)==nread);
    md_close(fd);
    *pnbytes = (jint)nbytes;
    return image;
}

/* ------------------------------------------------------------------ */

void
check_binary_file(char *filename)
{
    unsigned char *image;
    unsigned char *p;
    unsigned       idsize;
    int            nbytes;
    int            nrecords;

    image = get_binary_file_image(filename, &nbytes);
    if ( image == NULL ) {
        check_printf("No file image: %s\n", filename);
        return;
    }
    p = image;
    CHECK_FOR_ERROR(strcmp((char*)p, gdata->header)==0);
    check_printf("Filename=%s, nbytes=%d, header=\"%s\"\n",
                        filename, nbytes, p);
    p+=((int)strlen((char*)p)+1);
    idsize = read_u4(&p);
    CHECK_FOR_ERROR(idsize==sizeof(HprofId));
    (void)read_u4(&p);
    (void)read_u4(&p);
    /* LINTED */
    nrecords = check_tags(p, nbytes - (int)( p - image ) );
    check_printf("#%d total records found in %d bytes\n", nrecords, nbytes);
    HPROF_FREE(image);
}

Other Java examples (source code examples)

Here is a short list of links related to this Java hprof_check.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.