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."); } }