FileDocCategorySizeDatePackage
HprofParser.javaAPI DocAndroid 1.5 API21340Wed May 06 22:41:02 BST 2009com.android.hit

HprofParser

public class HprofParser extends Object

Fields Summary
private static final int
STRING_IN_UTF8
private static final int
LOAD_CLASS
private static final int
UNLOAD_CLASS
private static final int
STACK_FRAME
private static final int
STACK_TRACE
private static final int
ALLOC_SITES
private static final int
HEAP_SUMMARY
private static final int
START_THREAD
private static final int
END_THREAD
private static final int
HEAP_DUMP
private static final int
HEAP_DUMP_SEGMENT
private static final int
HEAP_DUMP_END
private static final int
CPU_SAMPLES
private static final int
CONTROL_SETTINGS
private static final int
ROOT_UNKNOWN
private static final int
ROOT_JNI_GLOBAL
private static final int
ROOT_JNI_LOCAL
private static final int
ROOT_JAVA_FRAME
private static final int
ROOT_NATIVE_STACK
private static final int
ROOT_STICKY_CLASS
private static final int
ROOT_THREAD_BLOCK
private static final int
ROOT_MONITOR_USED
private static final int
ROOT_THREAD_OBJECT
private static final int
ROOT_CLASS_DUMP
private static final int
ROOT_INSTANCE_DUMP
private static final int
ROOT_OBJECT_ARRAY_DUMP
private static final int
ROOT_PRIMITIVE_ARRAY_DUMP
private static final int
ROOT_HEAP_DUMP_INFO
Android format addition Specifies information about which heap certain objects came from. When a sub-tag of this type appears in a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record, entries that follow it will be associated with the specified heap. The HEAP_DUMP_INFO data is reset at the end of the HEAP_DUMP[_SEGMENT]. Multiple HEAP_DUMP_INFO entries may appear in a single HEAP_DUMP[_SEGMENT]. Format: u1: Tag value (0xFE) u4: heap ID ID: heap name string ID
private static final int
ROOT_INTERNED_STRING
private static final int
ROOT_FINALIZING
private static final int
ROOT_DEBUGGER
private static final int
ROOT_REFERENCE_CLEANUP
private static final int
ROOT_VM_INTERNAL
private static final int
ROOT_JNI_MONITOR
private static final int
ROOT_UNREACHABLE
private static final int
ROOT_PRIMITIVE_ARRAY_NODATA
DataInputStream
mInput
int
mIdSize
State
mState
byte[]
mFieldBuffer
HashMap
mStrings
HashMap
mClassNames
Constructors Summary
public HprofParser(DataInputStream in)


       
        mInput = in;
    
Methods Summary
private intloadBasicObj(RootType type)

        long id = readId();
        RootObj root = new RootObj(type, id);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize;
    
private voidloadClass()

        DataInputStream in = mInput;
        int serial = in.readInt();
        long id = readId();
        int stackTrace = in.readInt();              //  unused
        String name = mStrings.get(readId());
        
        mClassNames.put(id, name);
    
private intloadClassDump()

        int bytesRead = 0;
        DataInputStream in = mInput;
        long id = readId();
        int stackSerialNumber = in.readInt();
        StackTrace stack = mState.getStackTrace(stackSerialNumber);
        long superClassId = readId();
        long classLoaderId = readId();
        long signersId = readId();
        long protectionDomainId = readId();
        long reserved1 = readId();
        long reserved2 = readId();
        int instanceSize = in.readInt();

        bytesRead = (7 * mIdSize) + 4 + 4;

        //  Skip over the constant pool
        int numEntries = in.readUnsignedShort();
        bytesRead += 2;
        
        for (int i = 0; i < numEntries; i++) {
            in.readUnsignedShort();
            bytesRead += 2 + skipValue();
        }

        //  Static fields
        numEntries = in.readUnsignedShort();
        bytesRead += 2;

        String[] staticFieldNames = new String[numEntries];
        int[] staticFieldTypes = new int[numEntries];
        ByteArrayOutputStream staticFieldValues = new ByteArrayOutputStream();
        byte[] buffer = mFieldBuffer;
        
        for (int i = 0; i < numEntries; i++) {
            staticFieldNames[i] = mStrings.get(readId());

            int fieldType = in.readByte();
            int fieldSize = Types.getTypeSize(fieldType);
            staticFieldTypes[i] = fieldType;

            in.readFully(buffer, 0, fieldSize);
            staticFieldValues.write(buffer, 0, fieldSize);

            bytesRead += mIdSize + 1 + fieldSize;
        }
        
        //  Instance fields
        numEntries = in.readUnsignedShort();
        bytesRead += 2;
        
        String[] names = new String[numEntries];
        int[] types = new int[numEntries];
        
        for (int i = 0; i < numEntries; i++) {
            long fieldName = readId();
            int type = in.readUnsignedByte();

            names[i] = mStrings.get(fieldName);
            types[i] = type;

            bytesRead += mIdSize + 1;
        }
        
        ClassObj theClass = new ClassObj(id, stack, mClassNames.get(id));

        theClass.setStaticFieldNames(staticFieldNames);
        theClass.setStaticFieldTypes(staticFieldTypes);
        theClass.setStaticFieldValues(staticFieldValues.toByteArray());

        theClass.setSuperclassId(superClassId);
        theClass.setFieldNames(names);
        theClass.setFieldTypes(types);
        theClass.setSize(instanceSize);
        
        theClass.setHeap(mState.mCurrentHeap);

        mState.addClass(id, theClass);
        
        return bytesRead;
    
private voidloadHeapDump(int length)

        DataInputStream in = mInput;
        
        while (length > 0) {
            int tag = in.readUnsignedByte();
            length--;
            
            switch (tag) {
                case ROOT_UNKNOWN:
                    length -= loadBasicObj(RootType.UNKNOWN);
                    break;
                    
                case ROOT_JNI_GLOBAL:
                    length -= loadBasicObj(RootType.NATIVE_STATIC);
                    readId();   //  ignored
                    length -= mIdSize;
                    break;
                    
                case ROOT_JNI_LOCAL:
                    length -= loadJniLocal();
                    break;
                    
                case ROOT_JAVA_FRAME:
                    length -= loadJavaFrame();
                    break;
                    
                case ROOT_NATIVE_STACK:
                    length -= loadNativeStack();
                    break;
                    
                case ROOT_STICKY_CLASS:
                    length -= loadBasicObj(RootType.SYSTEM_CLASS);
                    break;
                    
                case ROOT_THREAD_BLOCK:
                    length -= loadThreadBlock();
                    break;
                    
                case ROOT_MONITOR_USED:
                    length -= loadBasicObj(RootType.BUSY_MONITOR);
                    break;
                    
                case ROOT_THREAD_OBJECT:
                    length -= loadThreadObject();
                    break;
                    
                case ROOT_CLASS_DUMP:
                    length -= loadClassDump();
                    break;
                    
                case ROOT_INSTANCE_DUMP:
                    length -= loadInstanceDump();
                    break;
                    
                case ROOT_OBJECT_ARRAY_DUMP:
                    length -= loadObjectArrayDump();
                    break;
                    
                case ROOT_PRIMITIVE_ARRAY_DUMP:
                    length -= loadPrimitiveArrayDump();
                    break;

                case ROOT_PRIMITIVE_ARRAY_NODATA:
                    System.err.println("+--- PRIMITIVE ARRAY NODATA DUMP");
                    length -= loadPrimitiveArrayDump();

                    throw new IllegalArgumentException(
                        "Don't know how to load a nodata array");
                
                case ROOT_HEAP_DUMP_INFO:
                    int heapId = mInput.readInt();
                    long heapNameId = readId();
                    String heapName = mStrings.get(heapNameId);
                    
                    mState.setHeapTo(heapId, heapName);
                    length -= 4 + mIdSize;
                    break;
                
                case ROOT_INTERNED_STRING:
                    length -= loadBasicObj(RootType.INTERNED_STRING);
                    break;
                    
                case ROOT_FINALIZING:
                    length -= loadBasicObj(RootType.FINALIZING);
                    break;
                    
                case ROOT_DEBUGGER:
                    length -= loadBasicObj(RootType.DEBUGGER);
                    break;
                    
                case ROOT_REFERENCE_CLEANUP:
                    length -= loadBasicObj(RootType.REFERENCE_CLEANUP);
                    break;
                    
                case ROOT_VM_INTERNAL:
                    length -= loadBasicObj(RootType.VM_INTERNAL);
                    break;
                    
                case ROOT_JNI_MONITOR:
                    length -= loadJniMonitor();
                    break;
                    
                case ROOT_UNREACHABLE:
                    length -= loadBasicObj(RootType.UNREACHABLE);
                    break;
                    
                default:
                    throw new IllegalArgumentException(
                        "loadHeapDump loop with unknown tag " + tag 
                        + " with " + mInput.available() 
                        + " bytes possibly remaining");
            }
        }
    
private intloadInstanceDump()

        long id = readId();
        int stackId = mInput.readInt();
        StackTrace stack = mState.getStackTrace(stackId);
        long classId = readId();
        int remaining = mInput.readInt();
        ClassInstance instance = new ClassInstance(id, stack, classId);

        instance.loadFieldData(mInput, remaining);
        instance.setHeap(mState.mCurrentHeap);
        mState.addInstance(id, instance);
        
        return mIdSize + 4 + mIdSize + 4 + remaining;
    
private intloadJavaFrame()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        int stackFrameNumber = mInput.readInt();
        ThreadObj thread = mState.getThread(threadSerialNumber);
        StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace, 
            stackFrameNumber);
        RootObj root = new RootObj(RootType.JAVA_LOCAL, id, threadSerialNumber, 
            trace);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize + 4 + 4;
    
private intloadJniLocal()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        int stackFrameNumber = mInput.readInt();
        ThreadObj thread = mState.getThread(threadSerialNumber);
        StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace, 
            stackFrameNumber);
        RootObj root = new RootObj(RootType.NATIVE_LOCAL, id, 
            threadSerialNumber, trace);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize + 4 + 4;
    
private intloadJniMonitor()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        int stackDepth = mInput.readInt();
        ThreadObj thread = mState.getThread(threadSerialNumber);
        StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace, 
            stackDepth);
        RootObj root = new RootObj(RootType.NATIVE_MONITOR, id, 
            threadSerialNumber, trace);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize + 4 + 4;
    
private intloadNativeStack()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        ThreadObj thread = mState.getThread(threadSerialNumber);
        StackTrace trace = mState.getStackTrace(thread.mStackTrace);
        RootObj root = new RootObj(RootType.NATIVE_STACK, id, 
            threadSerialNumber, trace);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize + 4;
    
private intloadObjectArrayDump()

        long id = readId();
        int stackId = mInput.readInt();
        StackTrace stack = mState.getStackTrace(stackId);
        int numElements = mInput.readInt();
        long classId = readId();
        int totalBytes = numElements * mIdSize;
        byte[] data = new byte[totalBytes];
        String className = mClassNames.get(classId);
        
        mInput.readFully(data);

        ArrayInstance array = new ArrayInstance(id, stack, Types.OBJECT, 
            numElements, data);
        
        array.mClassId = classId;
        array.setHeap(mState.mCurrentHeap);
        mState.addInstance(id, array);

        return mIdSize + 4 + 4 + mIdSize + totalBytes;
    
private intloadPrimitiveArrayDump()

        long id = readId();
        int stackId = mInput.readInt();
        StackTrace stack = mState.getStackTrace(stackId);
        int numElements = mInput.readInt();
        int type = mInput.readUnsignedByte();
        int size = Types.getTypeSize(type);
        int totalBytes = numElements * size;
        byte[] data = new byte[totalBytes];
        
        mInput.readFully(data);

        ArrayInstance array = new ArrayInstance(id, stack, type, numElements, 
            data);
        
        array.setHeap(mState.mCurrentHeap);
        mState.addInstance(id, array);
        
        return mIdSize + 4 + 4 + 1 + totalBytes;
    
private voidloadStackFrame()

        long id = readId();
        String methodName = mStrings.get(readId());
        String methodSignature = mStrings.get(readId());
        String sourceFile = mStrings.get(readId());
        int serial = mInput.readInt();
        int lineNumber = mInput.readInt();
        
        StackFrame frame = new StackFrame(id, methodName, methodSignature, 
            sourceFile, serial, lineNumber);

        mState.addStackFrame(frame);
    
private voidloadStackTrace()

        int serialNumber = mInput.readInt();
        int threadSerialNumber = mInput.readInt();
        final int numFrames = mInput.readInt();
        StackFrame[] frames = new StackFrame[numFrames];
        
        for (int i = 0; i < numFrames; i++) {
            frames[i] = mState.getStackFrame(readId());
        }
        
        StackTrace trace = new StackTrace(serialNumber, threadSerialNumber, 
            frames);

        mState.addStackTrace(trace);
    
private voidloadString(int length)

        long id = readId();
        String string = readUTF8(length);
        
        mStrings.put(id, string);
    
private intloadThreadBlock()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        ThreadObj thread = mState.getThread(threadSerialNumber);
        StackTrace stack = mState.getStackTrace(thread.mStackTrace);
        RootObj root = new RootObj(RootType.THREAD_BLOCK, id, 
            threadSerialNumber, stack);
        
        root.setHeap(mState.mCurrentHeap);
        mState.addRoot(root);
        
        return mIdSize + 4;
    
private intloadThreadObject()

        long id = readId();
        int threadSerialNumber = mInput.readInt();
        int stackSerialNumber = mInput.readInt();
        ThreadObj thread = new ThreadObj(id, stackSerialNumber);
        
        mState.addThread(thread, threadSerialNumber);
        
        return mIdSize + 4 + 4;
    
public final Stateparse()

        State state = new State();
        mState = state;

        try {
            String  s = readNullTerminatedString();
            DataInputStream in = mInput;
            
            mIdSize = in.readInt();
            Types.setIdSize(mIdSize);
            
            in.readLong();  //  Timestamp, ignored for now
            
            while (true) {
                int tag = in.readUnsignedByte();
                int timestamp = in.readInt();
                int length = in.readInt();

                switch (tag) {
                    case STRING_IN_UTF8:
                        loadString(length - 4);
                        break;
                    
                    case LOAD_CLASS:
                        loadClass();
                        break;

                    case STACK_FRAME:
                        loadStackFrame();
                        break;

                    case STACK_TRACE:
                        loadStackTrace();
                        break;

                    case HEAP_DUMP:
                        loadHeapDump(length);
                        mState.setToDefaultHeap();
                        break;
                        
                    case HEAP_DUMP_SEGMENT:
                        loadHeapDump(length);
                        mState.setToDefaultHeap();
                        break;

                    default:
                        skipFully(length);
                }

            }
        } catch (EOFException eof) {
            //  this is fine
        } catch (Exception e) {
            e.printStackTrace();
        }

        mState.resolveReferences();
        
        return state;
    
private longreadId()

        switch (mIdSize) {
            case 1: return mInput.readUnsignedByte();
            case 2: return mInput.readUnsignedShort();
            case 4: return ((long) mInput.readInt()) & 0x00000000ffffffffL;
            case 8: return mInput.readLong();
        }
        
        throw new IllegalArgumentException("ID Length must be 1, 2, 4, or 8");
    
private java.lang.StringreadNullTerminatedString()

        StringBuilder s = new StringBuilder();
        DataInputStream in = mInput;

        for (int c = in.read(); c != 0; c = in.read()) {
            s.append((char) c);
        }
        
        return s.toString();
    
private java.lang.StringreadUTF8(int length)

        byte[] b = new byte[length];
        
        mInput.read(b);

        return new String(b, "utf-8");
    
private voidskipFully(long numBytes)

        while (numBytes > 0) {
            long skipped = mInput.skip(numBytes);
            
            numBytes -= skipped;
        }
    
private intskipValue()

        int type = mInput.readUnsignedByte();
        int size = Types.getTypeSize(type);
        
        skipFully(size);

        return size + 1;