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

Java example source code file (HprofReader.java)

This example Java source code file (HprofReader.java) 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

hashtable, ignoring, integer, ioexception, javafield, javathing, long, profile, root, stackframe, stacktrace, string, threadobject, util, version_jdk12beta4

The HprofReader.java Java example source code

/*
 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


/*
 * The Original Code is HAT. The Initial Developer of the
 * Original Code is Bill Foote, with contributions from others
 * at JavaSoft/Sun.
 */

package com.sun.tools.hat.internal.parser;

import java.io.*;
import java.util.Date;
import java.util.Hashtable;
import com.sun.tools.hat.internal.model.ArrayTypeCodes;
import com.sun.tools.hat.internal.model.*;

/**
 * Object that's used to read a hprof file.
 *
 * @author      Bill Foote
 */

public class HprofReader extends Reader /* imports */ implements ArrayTypeCodes {

    final static int MAGIC_NUMBER = 0x4a415641;
    // That's "JAVA", the first part of "JAVA PROFILE ..."
    private final static String[] VERSIONS = {
            " PROFILE 1.0\0",
            " PROFILE 1.0.1\0",
            " PROFILE 1.0.2\0",
    };

    private final static int VERSION_JDK12BETA3 = 0;
    private final static int VERSION_JDK12BETA4 = 1;
    private final static int VERSION_JDK6       = 2;
    // These version numbers are indices into VERSIONS.  The instance data
    // member version is set to one of these, and it drives decisions when
    // reading the file.
    //
    // Version 1.0.1 added HPROF_GC_PRIM_ARRAY_DUMP, which requires no
    // version-sensitive parsing.
    //
    // Version 1.0.1 changed the type of a constant pool entry from a signature
    // to a typecode.
    //
    // Version 1.0.2 added HPROF_HEAP_DUMP_SEGMENT and HPROF_HEAP_DUMP_END
    // to allow a large heap to be dumped as a sequence of heap dump segments.
    //
    // The HPROF agent in J2SE 1.2 through to 5.0 generate a version 1.0.1
    // file. In Java SE 6.0 the version is either 1.0.1 or 1.0.2 depending on
    // the size of the heap (normally it will be 1.0.1 but for multi-GB
    // heaps the heap dump will not fit in a HPROF_HEAP_DUMP record so the
    // dump is generated as version 1.0.2).

    //
    // Record types:
    //
    static final int HPROF_UTF8          = 0x01;
    static final int HPROF_LOAD_CLASS    = 0x02;
    static final int HPROF_UNLOAD_CLASS  = 0x03;
    static final int HPROF_FRAME         = 0x04;
    static final int HPROF_TRACE         = 0x05;
    static final int HPROF_ALLOC_SITES   = 0x06;
    static final int HPROF_HEAP_SUMMARY  = 0x07;

    static final int HPROF_START_THREAD  = 0x0a;
    static final int HPROF_END_THREAD    = 0x0b;

    static final int HPROF_HEAP_DUMP     = 0x0c;

    static final int HPROF_CPU_SAMPLES   = 0x0d;
    static final int HPROF_CONTROL_SETTINGS = 0x0e;
    static final int HPROF_LOCKSTATS_WAIT_TIME = 0x10;
    static final int HPROF_LOCKSTATS_HOLD_TIME = 0x11;

    static final int HPROF_GC_ROOT_UNKNOWN       = 0xff;
    static final int HPROF_GC_ROOT_JNI_GLOBAL    = 0x01;
    static final int HPROF_GC_ROOT_JNI_LOCAL     = 0x02;
    static final int HPROF_GC_ROOT_JAVA_FRAME    = 0x03;
    static final int HPROF_GC_ROOT_NATIVE_STACK  = 0x04;
    static final int HPROF_GC_ROOT_STICKY_CLASS  = 0x05;
    static final int HPROF_GC_ROOT_THREAD_BLOCK  = 0x06;
    static final int HPROF_GC_ROOT_MONITOR_USED  = 0x07;
    static final int HPROF_GC_ROOT_THREAD_OBJ    = 0x08;

    static final int HPROF_GC_CLASS_DUMP         = 0x20;
    static final int HPROF_GC_INSTANCE_DUMP      = 0x21;
    static final int HPROF_GC_OBJ_ARRAY_DUMP         = 0x22;
    static final int HPROF_GC_PRIM_ARRAY_DUMP         = 0x23;

    static final int HPROF_HEAP_DUMP_SEGMENT     = 0x1c;
    static final int HPROF_HEAP_DUMP_END         = 0x2c;

    private final static int T_CLASS = 2;

    private int version;        // The version of .hprof being read

    private int debugLevel;
    private long currPos;        // Current position in the file

    private int dumpsToSkip;
    private boolean callStack;  // If true, read the call stack of objects

    private int identifierSize;         // Size, in bytes, of identifiers.
    private Hashtable<Long, String> names;

    // Hashtable<Integer, ThreadObject>, used to map the thread sequence number
    // (aka "serial number") to the thread object ID for
    // HPROF_GC_ROOT_THREAD_OBJ.  ThreadObject is a trivial inner class,
    // at the end of this file.
    private Hashtable<Integer, ThreadObject> threadObjects;

    // Hashtable<Long, String>, maps class object ID to class name
    // (with / converted to .)
    private Hashtable<Long, String> classNameFromObjectID;

    // Hashtable<Integer, Integer>, maps class serial # to class object ID
    private Hashtable<Integer, String> classNameFromSerialNo;

    // Hashtable<Long, StackFrame> maps stack frame ID to StackFrame.
    // Null if we're not tracking them.
    private Hashtable<Long, StackFrame> stackFrames;

    // Hashtable<Integer, StackTrace> maps stack frame ID to StackTrace
    // Null if we're not tracking them.
    private Hashtable<Integer, StackTrace> stackTraces;

    private Snapshot snapshot;

    public HprofReader(String fileName, PositionDataInputStream in,
                       int dumpNumber, boolean callStack, int debugLevel)
                       throws IOException {
        super(in);
        RandomAccessFile file = new RandomAccessFile(fileName, "r");
        this.snapshot = new Snapshot(MappedReadBuffer.create(file));
        this.dumpsToSkip = dumpNumber - 1;
        this.callStack = callStack;
        this.debugLevel = debugLevel;
        names = new Hashtable<Long, String>();
        threadObjects = new Hashtable<Integer, ThreadObject>(43);
        classNameFromObjectID = new Hashtable<Long, String>();
        if (callStack) {
            stackFrames = new Hashtable<Long, StackFrame>(43);
            stackTraces = new Hashtable<Integer, StackTrace>(43);
            classNameFromSerialNo = new Hashtable<Integer, String>();
        }
    }

    public Snapshot read() throws IOException {
        currPos = 4;    // 4 because of the magic number
        version = readVersionHeader();
        identifierSize = in.readInt();
        snapshot.setIdentifierSize(identifierSize);
        if (version >= VERSION_JDK12BETA4) {
            snapshot.setNewStyleArrayClass(true);
        } else {
            snapshot.setNewStyleArrayClass(false);
        }

        currPos += 4;
        if (identifierSize != 4 && identifierSize != 8) {
            throw new IOException("I'm sorry, but I can't deal with an identifier size of " + identifierSize + ".  I can only deal with 4 or 8.");
        }
        System.out.println("Dump file created " + (new Date(in.readLong())));
        currPos += 8;

        for (;;) {
            int type;
            try {
                type = in.readUnsignedByte();
            } catch (EOFException ignored) {
                break;
            }
            in.readInt();       // Timestamp of this record
            // Length of record: readInt() will return negative value for record
            // length >2GB.  so store 32bit value in long to keep it unsigned.
            long length = in.readInt() & 0xffffffffL;
            if (debugLevel > 0) {
                System.out.println("Read record type " + type
                                   + ", length " + length
                                   + " at position " + toHex(currPos));
            }
            if (length < 0) {
                throw new IOException("Bad record length of " + length
                                      + " at byte " + toHex(currPos+5)
                                      + " of file.");
            }
            currPos += 9 + length;
            switch (type) {
                case HPROF_UTF8: {
                    long id = readID();
                    byte[] chars = new byte[(int)length - identifierSize];
                    in.readFully(chars);
                    names.put(new Long(id), new String(chars));
                    break;
                }
                case HPROF_LOAD_CLASS: {
                    int serialNo = in.readInt();        // Not used
                    long classID = readID();
                    int stackTraceSerialNo = in.readInt();
                    long classNameID = readID();
                    Long classIdI = new Long(classID);
                    String nm = getNameFromID(classNameID).replace('/', '.');
                    classNameFromObjectID.put(classIdI, nm);
                    if (classNameFromSerialNo != null) {
                        classNameFromSerialNo.put(new Integer(serialNo), nm);
                    }
                    break;
                }

                case HPROF_HEAP_DUMP: {
                    if (dumpsToSkip <= 0) {
                        try {
                            readHeapDump(length, currPos);
                        } catch (EOFException exp) {
                            handleEOF(exp, snapshot);
                        }
                        if (debugLevel > 0) {
                            System.out.println("    Finished processing instances in heap dump.");
                        }
                        return snapshot;
                    } else {
                        dumpsToSkip--;
                        skipBytes(length);
                    }
                    break;
                }

                case HPROF_HEAP_DUMP_END: {
                    if (version >= VERSION_JDK6) {
                        if (dumpsToSkip <= 0) {
                            skipBytes(length);  // should be no-op
                            return snapshot;
                        } else {
                            // skip this dump (of the end record for a sequence of dump segments)
                            dumpsToSkip--;
                        }
                    } else {
                        // HPROF_HEAP_DUMP_END only recognized in >= 1.0.2
                        warn("Ignoring unrecognized record type " + type);
                    }
                    skipBytes(length);  // should be no-op
                    break;
                }

                case HPROF_HEAP_DUMP_SEGMENT: {
                    if (version >= VERSION_JDK6) {
                        if (dumpsToSkip <= 0) {
                            try {
                                // read the dump segment
                                readHeapDump(length, currPos);
                            } catch (EOFException exp) {
                                handleEOF(exp, snapshot);
                            }
                        } else {
                            // all segments comprising the heap dump will be skipped
                            skipBytes(length);
                        }
                    } else {
                        // HPROF_HEAP_DUMP_SEGMENT only recognized in >= 1.0.2
                        warn("Ignoring unrecognized record type " + type);
                        skipBytes(length);
                    }
                    break;
                }

                case HPROF_FRAME: {
                    if (stackFrames == null) {
                        skipBytes(length);
                    } else {
                        long id = readID();
                        String methodName = getNameFromID(readID());
                        String methodSig = getNameFromID(readID());
                        String sourceFile = getNameFromID(readID());
                        int classSer = in.readInt();
                        String className = classNameFromSerialNo.get(new Integer(classSer));
                        int lineNumber = in.readInt();
                        if (lineNumber < StackFrame.LINE_NUMBER_NATIVE) {
                            warn("Weird stack frame line number:  " + lineNumber);
                            lineNumber = StackFrame.LINE_NUMBER_UNKNOWN;
                        }
                        stackFrames.put(new Long(id),
                                        new StackFrame(methodName, methodSig,
                                                       className, sourceFile,
                                                       lineNumber));
                    }
                    break;
                }
                case HPROF_TRACE: {
                    if (stackTraces == null) {
                        skipBytes(length);
                    } else {
                        int serialNo = in.readInt();
                        int threadSeq = in.readInt();   // Not used
                        StackFrame[] frames = new StackFrame[in.readInt()];
                        for (int i = 0; i < frames.length; i++) {
                            long fid = readID();
                            frames[i] = stackFrames.get(new Long(fid));
                            if (frames[i] == null) {
                                throw new IOException("Stack frame " + toHex(fid) + " not found");
                            }
                        }
                        stackTraces.put(new Integer(serialNo),
                                        new StackTrace(frames));
                    }
                    break;
                }
                case HPROF_UNLOAD_CLASS:
                case HPROF_ALLOC_SITES:
                case HPROF_START_THREAD:
                case HPROF_END_THREAD:
                case HPROF_HEAP_SUMMARY:
                case HPROF_CPU_SAMPLES:
                case HPROF_CONTROL_SETTINGS:
                case HPROF_LOCKSTATS_WAIT_TIME:
                case HPROF_LOCKSTATS_HOLD_TIME:
                {
                    // Ignore these record types
                    skipBytes(length);
                    break;
                }
                default: {
                    skipBytes(length);
                    warn("Ignoring unrecognized record type " + type);
                }
            }
        }

        return snapshot;
    }

    private void skipBytes(long length) throws IOException {
        in.skipBytes((int)length);
    }

    private int readVersionHeader() throws IOException {
        int candidatesLeft = VERSIONS.length;
        boolean[] matched = new boolean[VERSIONS.length];
        for (int i = 0; i < candidatesLeft; i++) {
            matched[i] = true;
        }

        int pos = 0;
        while (candidatesLeft > 0) {
            char c = (char) in.readByte();
            currPos++;
            for (int i = 0; i < VERSIONS.length; i++) {
                if (matched[i]) {
                    if (c != VERSIONS[i].charAt(pos)) {   // Not matched
                        matched[i] = false;
                        --candidatesLeft;
                    } else if (pos == VERSIONS[i].length() - 1) {  // Full match
                        return i;
                    }
                }
            }
            ++pos;
        }
        throw new IOException("Version string not recognized at byte " + (pos+3));
    }

    private void readHeapDump(long bytesLeft, long posAtEnd) throws IOException {
        while (bytesLeft > 0) {
            int type = in.readUnsignedByte();
            if (debugLevel > 0) {
                System.out.println("    Read heap sub-record type " + type
                                   + " at position "
                                   + toHex(posAtEnd - bytesLeft));
            }
            bytesLeft--;
            switch(type) {
                case HPROF_GC_ROOT_UNKNOWN: {
                    long id = readID();
                    bytesLeft -= identifierSize;
                    snapshot.addRoot(new Root(id, 0, Root.UNKNOWN, ""));
                    break;
                }
                case HPROF_GC_ROOT_THREAD_OBJ: {
                    long id = readID();
                    int threadSeq = in.readInt();
                    int stackSeq = in.readInt();
                    bytesLeft -= identifierSize + 8;
                    threadObjects.put(new Integer(threadSeq),
                                      new ThreadObject(id, stackSeq));
                    break;
                }
                case HPROF_GC_ROOT_JNI_GLOBAL: {
                    long id = readID();
                    long globalRefId = readID();        // Ignored, for now
                    bytesLeft -= 2*identifierSize;
                    snapshot.addRoot(new Root(id, 0, Root.NATIVE_STATIC, ""));
                    break;
                }
                case HPROF_GC_ROOT_JNI_LOCAL: {
                    long id = readID();
                    int threadSeq = in.readInt();
                    int depth = in.readInt();
                    bytesLeft -= identifierSize + 8;
                    ThreadObject to = getThreadObjectFromSequence(threadSeq);
                    StackTrace st = getStackTraceFromSerial(to.stackSeq);
                    if (st != null) {
                        st = st.traceForDepth(depth+1);
                    }
                    snapshot.addRoot(new Root(id, to.threadId,
                                              Root.NATIVE_LOCAL, "", st));
                    break;
                }
                case HPROF_GC_ROOT_JAVA_FRAME: {
                    long id = readID();
                    int threadSeq = in.readInt();
                    int depth = in.readInt();
                    bytesLeft -= identifierSize + 8;
                    ThreadObject to = getThreadObjectFromSequence(threadSeq);
                    StackTrace st = getStackTraceFromSerial(to.stackSeq);
                    if (st != null) {
                        st = st.traceForDepth(depth+1);
                    }
                    snapshot.addRoot(new Root(id, to.threadId,
                                              Root.JAVA_LOCAL, "", st));
                    break;
                }
                case HPROF_GC_ROOT_NATIVE_STACK: {
                    long id = readID();
                    int threadSeq = in.readInt();
                    bytesLeft -= identifierSize + 4;
                    ThreadObject to = getThreadObjectFromSequence(threadSeq);
                    StackTrace st = getStackTraceFromSerial(to.stackSeq);
                    snapshot.addRoot(new Root(id, to.threadId,
                                              Root.NATIVE_STACK, "", st));
                    break;
                }
                case HPROF_GC_ROOT_STICKY_CLASS: {
                    long id = readID();
                    bytesLeft -= identifierSize;
                    snapshot.addRoot(new Root(id, 0, Root.SYSTEM_CLASS, ""));
                    break;
                }
                case HPROF_GC_ROOT_THREAD_BLOCK: {
                    long id = readID();
                    int threadSeq = in.readInt();
                    bytesLeft -= identifierSize + 4;
                    ThreadObject to = getThreadObjectFromSequence(threadSeq);
                    StackTrace st = getStackTraceFromSerial(to.stackSeq);
                    snapshot.addRoot(new Root(id, to.threadId,
                                     Root.THREAD_BLOCK, "", st));
                    break;
                }
                case HPROF_GC_ROOT_MONITOR_USED: {
                    long id = readID();
                    bytesLeft -= identifierSize;
                    snapshot.addRoot(new Root(id, 0, Root.BUSY_MONITOR, ""));
                    break;
                }
                case HPROF_GC_CLASS_DUMP: {
                    int bytesRead = readClass();
                    bytesLeft -= bytesRead;
                    break;
                }
                case HPROF_GC_INSTANCE_DUMP: {
                    int bytesRead = readInstance();
                    bytesLeft -= bytesRead;
                    break;
                }
                case HPROF_GC_OBJ_ARRAY_DUMP: {
                    int bytesRead = readArray(false);
                    bytesLeft -= bytesRead;
                    break;
                }
                case HPROF_GC_PRIM_ARRAY_DUMP: {
                    int bytesRead = readArray(true);
                    bytesLeft -= bytesRead;
                    break;
                }
                default: {
                    throw new IOException("Unrecognized heap dump sub-record type:  " + type);
                }
            }
        }
        if (bytesLeft != 0) {
            warn("Error reading heap dump or heap dump segment:  Byte count is " + bytesLeft + " instead of 0");
            skipBytes(bytesLeft);
        }
        if (debugLevel > 0) {
            System.out.println("    Finished heap sub-records.");
        }
    }

    private long readID() throws IOException {
        return (identifierSize == 4)?
            (Snapshot.SMALL_ID_MASK & (long)in.readInt()) : in.readLong();
    }

    //
    // Read a java value.  If result is non-null, it's expected to be an
    // array of one element.  We use it to fake multiple return values.
    // @returns the number of bytes read
    //
    private int readValue(JavaThing[] resultArr) throws IOException {
        byte type = in.readByte();
        return 1 + readValueForType(type, resultArr);
    }

    private int readValueForType(byte type, JavaThing[] resultArr)
            throws IOException {
        if (version >= VERSION_JDK12BETA4) {
            type = signatureFromTypeId(type);
        }
        return readValueForTypeSignature(type, resultArr);
    }

    private int readValueForTypeSignature(byte type, JavaThing[] resultArr)
            throws IOException {
        switch (type) {
            case '[':
            case 'L': {
                long id = readID();
                if (resultArr != null) {
                    resultArr[0] = new JavaObjectRef(id);
                }
                return identifierSize;
            }
            case 'Z': {
                int b = in.readByte();
                if (b != 0 && b != 1) {
                    warn("Illegal boolean value read");
                }
                if (resultArr != null) {
                    resultArr[0] = new JavaBoolean(b != 0);
                }
                return 1;
            }
            case 'B': {
                byte b = in.readByte();
                if (resultArr != null) {
                    resultArr[0] = new JavaByte(b);
                }
                return 1;
            }
            case 'S': {
                short s = in.readShort();
                if (resultArr != null) {
                    resultArr[0] = new JavaShort(s);
                }
                return 2;
            }
            case 'C': {
                char ch = in.readChar();
                if (resultArr != null) {
                    resultArr[0] = new JavaChar(ch);
                }
                return 2;
            }
            case 'I': {
                int val = in.readInt();
                if (resultArr != null) {
                    resultArr[0] = new JavaInt(val);
                }
                return 4;
            }
            case 'J': {
                long val = in.readLong();
                if (resultArr != null) {
                    resultArr[0] = new JavaLong(val);
                }
                return 8;
            }
            case 'F': {
                float val = in.readFloat();
                if (resultArr != null) {
                    resultArr[0] = new JavaFloat(val);
                }
                return 4;
            }
            case 'D': {
                double val = in.readDouble();
                if (resultArr != null) {
                    resultArr[0] = new JavaDouble(val);
                }
                return 8;
            }
            default: {
                throw new IOException("Bad value signature:  " + type);
            }
        }
    }

    private ThreadObject getThreadObjectFromSequence(int threadSeq)
            throws IOException {
        ThreadObject to = threadObjects.get(new Integer(threadSeq));
        if (to == null) {
            throw new IOException("Thread " + threadSeq +
                                  " not found for JNI local ref");
        }
        return to;
    }

    private String getNameFromID(long id) throws IOException {
        return getNameFromID(new Long(id));
    }

    private String getNameFromID(Long id) throws IOException {
        if (id.longValue() == 0L) {
            return "";
        }
        String result = names.get(id);
        if (result == null) {
            warn("Name not found at " + toHex(id.longValue()));
            return "unresolved name " + toHex(id.longValue());
        }
        return result;
    }

    private StackTrace getStackTraceFromSerial(int ser) throws IOException {
        if (stackTraces == null) {
            return null;
        }
        StackTrace result = stackTraces.get(new Integer(ser));
        if (result == null) {
            warn("Stack trace not found for serial # " + ser);
        }
        return result;
    }

    //
    // Handle a HPROF_GC_CLASS_DUMP
    // Return number of bytes read
    //
    private int readClass() throws IOException {
        long id = readID();
        StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
        long superId = readID();
        long classLoaderId = readID();
        long signersId = readID();
        long protDomainId = readID();
        long reserved1 = readID();
        long reserved2 = readID();
        int instanceSize = in.readInt();
        int bytesRead = 7 * identifierSize + 8;

        int numConstPoolEntries = in.readUnsignedShort();
        bytesRead += 2;
        for (int i = 0; i < numConstPoolEntries; i++) {
            int index = in.readUnsignedShort(); // unused
            bytesRead += 2;
            bytesRead += readValue(null);       // We ignore the values
        }

        int numStatics = in.readUnsignedShort();
        bytesRead += 2;
        JavaThing[] valueBin = new JavaThing[1];
        JavaStatic[] statics = new JavaStatic[numStatics];
        for (int i = 0; i < numStatics; i++) {
            long nameId = readID();
            bytesRead += identifierSize;
            byte type = in.readByte();
            bytesRead++;
            bytesRead += readValueForType(type, valueBin);
            String fieldName = getNameFromID(nameId);
            if (version >= VERSION_JDK12BETA4) {
                type = signatureFromTypeId(type);
            }
            String signature = "" + ((char) type);
            JavaField f = new JavaField(fieldName, signature);
            statics[i] = new JavaStatic(f, valueBin[0]);
        }

        int numFields = in.readUnsignedShort();
        bytesRead += 2;
        JavaField[] fields = new JavaField[numFields];
        for (int i = 0; i < numFields; i++) {
            long nameId = readID();
            bytesRead += identifierSize;
            byte type = in.readByte();
            bytesRead++;
            String fieldName = getNameFromID(nameId);
            if (version >= VERSION_JDK12BETA4) {
                type = signatureFromTypeId(type);
            }
            String signature = "" + ((char) type);
            fields[i] = new JavaField(fieldName, signature);
        }
        String name = classNameFromObjectID.get(new Long(id));
        if (name == null) {
            warn("Class name not found for " + toHex(id));
            name = "unknown-name@" + toHex(id);
        }
        JavaClass c = new JavaClass(id, name, superId, classLoaderId, signersId,
                                    protDomainId, fields, statics,
                                    instanceSize);
        snapshot.addClass(id, c);
        snapshot.setSiteTrace(c, stackTrace);

        return bytesRead;
    }

    private String toHex(long addr) {
        return com.sun.tools.hat.internal.util.Misc.toHex(addr);
    }

    //
    // Handle a HPROF_GC_INSTANCE_DUMP
    // Return number of bytes read
    //
    private int readInstance() throws IOException {
        long start = in.position();
        long id = readID();
        StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
        long classID = readID();
        int bytesFollowing = in.readInt();
        int bytesRead = (2 * identifierSize) + 8 + bytesFollowing;
        JavaObject jobj = new JavaObject(classID, start);
        skipBytes(bytesFollowing);
        snapshot.addHeapObject(id, jobj);
        snapshot.setSiteTrace(jobj, stackTrace);
        return bytesRead;
    }

    //
    // Handle a HPROF_GC_OBJ_ARRAY_DUMP or HPROF_GC_PRIM_ARRAY_DUMP
    // Return number of bytes read
    //
    private int readArray(boolean isPrimitive) throws IOException {
        long start = in.position();
        long id = readID();
        StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
        int num = in.readInt();
        int bytesRead = identifierSize + 8;
        long elementClassID;
        if (isPrimitive) {
            elementClassID = in.readByte();
            bytesRead++;
        } else {
            elementClassID = readID();
            bytesRead += identifierSize;
        }

        // Check for primitive arrays:
        byte primitiveSignature = 0x00;
        int elSize = 0;
        if (isPrimitive || version < VERSION_JDK12BETA4) {
            switch ((int)elementClassID) {
                case T_BOOLEAN: {
                    primitiveSignature = (byte) 'Z';
                    elSize = 1;
                    break;
                }
                case T_CHAR: {
                    primitiveSignature = (byte) 'C';
                    elSize = 2;
                    break;
                }
                case T_FLOAT: {
                    primitiveSignature = (byte) 'F';
                    elSize = 4;
                    break;
                }
                case T_DOUBLE: {
                    primitiveSignature = (byte) 'D';
                    elSize = 8;
                    break;
                }
                case T_BYTE: {
                    primitiveSignature = (byte) 'B';
                    elSize = 1;
                    break;
                }
                case T_SHORT: {
                    primitiveSignature = (byte) 'S';
                    elSize = 2;
                    break;
                }
                case T_INT: {
                    primitiveSignature = (byte) 'I';
                    elSize = 4;
                    break;
                }
                case T_LONG: {
                    primitiveSignature = (byte) 'J';
                    elSize = 8;
                    break;
                }
            }
            if (version >= VERSION_JDK12BETA4 && primitiveSignature == 0x00) {
                throw new IOException("Unrecognized typecode:  "
                                        + elementClassID);
            }
        }
        if (primitiveSignature != 0x00) {
            int size = elSize * num;
            bytesRead += size;
            JavaValueArray va = new JavaValueArray(primitiveSignature, start);
            skipBytes(size);
            snapshot.addHeapObject(id, va);
            snapshot.setSiteTrace(va, stackTrace);
        } else {
            int sz = num * identifierSize;
            bytesRead += sz;
            JavaObjectArray arr = new JavaObjectArray(elementClassID, start);
            skipBytes(sz);
            snapshot.addHeapObject(id, arr);
            snapshot.setSiteTrace(arr, stackTrace);
        }
        return bytesRead;
    }

    private byte signatureFromTypeId(byte typeId) throws IOException {
        switch (typeId) {
            case T_CLASS: {
                return (byte) 'L';
            }
            case T_BOOLEAN: {
                return (byte) 'Z';
            }
            case T_CHAR: {
                return (byte) 'C';
            }
            case T_FLOAT: {
                return (byte) 'F';
            }
            case T_DOUBLE: {
                return (byte) 'D';
            }
            case T_BYTE: {
                return (byte) 'B';
            }
            case T_SHORT: {
                return (byte) 'S';
            }
            case T_INT: {
                return (byte) 'I';
            }
            case T_LONG: {
                return (byte) 'J';
            }
            default: {
                throw new IOException("Invalid type id of " + typeId);
            }
        }
    }

    private void handleEOF(EOFException exp, Snapshot snapshot) {
        if (debugLevel > 0) {
            exp.printStackTrace();
        }
        warn("Unexpected EOF. Will miss information...");
        // we have EOF, we have to tolerate missing references
        snapshot.setUnresolvedObjectsOK(true);
    }

    private void warn(String msg) {
        System.out.println("WARNING: " + msg);
    }

    //
    // A trivial data-holder class for HPROF_GC_ROOT_THREAD_OBJ.
    //
    private class ThreadObject {

        long threadId;
        int stackSeq;

        ThreadObject(long threadId, int stackSeq) {
            this.threadId = threadId;
            this.stackSeq = stackSeq;
        }
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java HprofReader.java 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.