/* * Copyright 2014 Edward Aftandilian. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.tufts.eaftan.hprofparser.handler.examples; import edu.tufts.eaftan.hprofparser.parser.datastructures.ClassInfo; import edu.tufts.eaftan.hprofparser.handler.NullRecordHandler; import edu.tufts.eaftan.hprofparser.parser.datastructures.AllocSite; import edu.tufts.eaftan.hprofparser.parser.datastructures.CPUSample; import edu.tufts.eaftan.hprofparser.parser.datastructures.Constant; import edu.tufts.eaftan.hprofparser.parser.datastructures.InstanceField; import edu.tufts.eaftan.hprofparser.parser.datastructures.Static; import edu.tufts.eaftan.hprofparser.parser.datastructures.Value; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; /** * Prints details for each record encountered. */ public class PrintHandler extends NullRecordHandler { private HashMap<Long, String> stringMap = new HashMap<Long, String>(); private HashMap<Long, ClassInfo> classMap = new HashMap<Long, ClassInfo>(); /* handler for file header */ @Override public void header(String format, int idSize, long time) { System.out.println(format); System.out.println(idSize); System.out.println(millisecondsDateToString(time)); } /* Handlers for top-level records */ @Override public void stringInUTF8(long id, String data) { // store string for later lookup stringMap.put(id, data); } @Override public void loadClass(int classSerialNum, long classObjId, int stackTraceSerialNum, long classNameStringId) { System.out.println("Load Class:"); System.out.println(" class serial num: " + classSerialNum); System.out.println(" class object id: " + classObjId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" class name string: " + stringMap.get(classNameStringId)); } @Override public void unloadClass(int classSerialNum) { System.out.println("Unload Class:"); System.out.println(" class serial num: " + classSerialNum); } @Override public void stackFrame(long stackFrameId, long methodNameStringId, long methodSigStringId, long sourceFileNameStringId, int classSerialNum, int location) { System.out.println("Stack Frame:"); System.out.println(" stack frame id: " + stackFrameId); System.out.println(" method name string: " + stringMap.get(methodNameStringId)); System.out.println(" method sig string: " + stringMap.get(methodSigStringId)); System.out.println(" source file name string: " + stringMap.get(sourceFileNameStringId)); System.out.println(" class serial num: " + classSerialNum); System.out.print(" location: "); switch (location) { case 0: System.out.println("no line information available"); break; case -1: System.out.println("unknown location"); break; case -2: System.out.println("compiled method"); break; case -3: System.out.println("native method"); break; default: System.out.println("line number " + location); break; } } @Override public void stackTrace(int stackTraceSerialNum, int threadSerialNum, int numFrames, long[] stackFrameIds) { System.out.println("Stack Trace:"); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" thread serial num: " + threadSerialNum); System.out.println(" num frames: " + numFrames); System.out.println(" stack frame ids:"); for (long sfi: stackFrameIds) { System.out.println(" " + sfi); } } @Override public void allocSites(short bitMaskFlags, float cutoffRatio, int totalLiveBytes, int totalLiveInstances, long totalBytesAllocated, long totalInstancesAllocated, AllocSite[] sites) { System.out.println("Alloc Sites:"); System.out.println(" bit mask flags: " + bitMaskFlags); System.out.println(" incremental vs. complete: " + testBitMask(bitMaskFlags, 0x1)); System.out.println(" sorted by allocation vs. line: " + testBitMask(bitMaskFlags, 0x2)); System.out.println(" whether to force GC: " + testBitMask(bitMaskFlags, 0x4)); System.out.println(" cutoff ratio: " + cutoffRatio); System.out.println(" total live bytes: " + totalLiveBytes); System.out.println(" total live instances: " + totalLiveInstances); System.out.println(" total bytes allocated: " + totalBytesAllocated); System.out.println(" total instances allocated: " + totalInstancesAllocated); for (int i=0; i<sites.length; i++) { System.out.println(" alloc site " + (i+1) + ":"); System.out.print(" array indicator: "); if (sites[i].arrayIndicator == 0) { System.out.println("not an array"); } else { System.out.println("array of " + getBasicType(sites[i].arrayIndicator)); } System.out.println(" class serial num: " + sites[i].classSerialNum); System.out.println(" stack trace serial num: " + sites[i].stackTraceSerialNum); System.out.println(" num live bytes: " + sites[i].numLiveBytes); System.out.println(" num live instances: " + sites[i].numLiveInstances); System.out.println(" num bytes allocated: " + sites[i].numBytesAllocated); System.out.println(" num instances allocated: " + sites[i].numInstancesAllocated); } } @Override public void heapSummary(int totalLiveBytes, int totalLiveInstances, long totalBytesAllocated, long totalInstancesAllocated) { System.out.println("Heap Summary:"); System.out.println(" total live bytes: " + totalLiveBytes); System.out.println(" total live instances: " + totalLiveInstances); System.out.println(" total bytes allocated: " + totalBytesAllocated); System.out.println(" total instances allocated: " + totalInstancesAllocated); } @Override public void startThread(int threadSerialNum, long threadObjectId, int stackTraceSerialNum, long threadNameStringId, long threadGroupNameId, long threadParentGroupNameId) { System.out.println("Start Thread:"); System.out.println(" thread serial num: " + threadSerialNum); System.out.println(" thread object id: " + threadObjectId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" thread name string: " + stringMap.get(threadNameStringId)); System.out.println(" thread group name id: " + stringMap.get(threadGroupNameId)); System.out.println(" thread parent group name id: " + stringMap.get(threadParentGroupNameId)); } @Override public void endThread(int threadSerialNum) { System.out.println("End Thread:"); System.out.println(" thread serial num: " + threadSerialNum); } @Override public void heapDump() { System.out.println("Heap Dump:"); } @Override public void heapDumpEnd() { System.out.println("Heap Dump End:"); } @Override public void heapDumpSegment() { System.out.println("Heap Dump Segment:"); } @Override public void cpuSamples(int totalNumOfSamples, CPUSample[] samples) { System.out.println("CPU Samples:"); System.out.println(" total num of samples: " + totalNumOfSamples); for (int i=0; i<samples.length; i++) { System.out.println(" cpu sample " + (i+1) + ":"); System.out.println(" number of samples: " + samples[i].numSamples); System.out.println(" stack trace serial num: " + samples[i].stackTraceSerialNum); } } @Override public void controlSettings(int bitMaskFlags, short stackTraceDepth) { System.out.println("Control Settings:"); System.out.println(" bit mask flags: " + bitMaskFlags); System.out.println(" alloc traces on/off: " + testBitMask(bitMaskFlags, 0x1)); System.out.println(" cpu sampling on/off: " + testBitMask(bitMaskFlags, 0x2)); System.out.println(" stack trace depth: " + stackTraceDepth); } /* Handlers for heap dump records */ @Override public void rootUnknown(long objId) { System.out.println("Root Unknown:"); System.out.println(" object id: " + objId); } @Override public void rootJNIGlobal(long objId, long JNIGlobalRefId) { System.out.println("Root JNI Global:"); System.out.println(" object id: " + objId); System.out.println(" JNI global ref id: " + JNIGlobalRefId); } @Override public void rootJNILocal(long objId, int threadSerialNum, int frameNum) { System.out.println("Root JNI Local:"); System.out.println(" object id: " + objId); System.out.println(" thread serial num: " + threadSerialNum); System.out.println(" frame num: " + frameNum); } @Override public void rootJavaFrame(long objId, int threadSerialNum, int frameNum) { System.out.println("Root Java Frame:"); System.out.println(" object id: " + objId); System.out.println(" thread serial num: " + threadSerialNum); System.out.println(" frame num: " + frameNum); } @Override public void rootNativeStack(long objId, int threadSerialNum) { System.out.println("Root Native Stack:"); System.out.println(" object id: " + objId); System.out.println(" thread serial num: " + threadSerialNum); } @Override public void rootStickyClass(long objId) { System.out.println("Root Sticky Class:"); System.out.println(" object id: " + objId); } @Override public void rootThreadBlock(long objId, int threadSerialNum) { System.out.println("Root Thread Block:"); System.out.println(" object id: " + objId); System.out.println(" thread serial num: " + threadSerialNum); } @Override public void rootMonitorUsed(long objId) { System.out.println("Root Monitor Used:"); System.out.println(" object id: " + objId); } @Override public void rootThreadObj(long objId, int threadSerialNum, int stackTraceSerialNum) { System.out.println("Root Thread Object:"); System.out.println(" object id: " + objId); System.out.println(" thread serial num: " + threadSerialNum); System.out.println(" stack trace serial num: " + stackTraceSerialNum); } @Override public void classDump(long classObjId, int stackTraceSerialNum, long superClassObjId, long classLoaderObjId, long signersObjId, long protectionDomainObjId, long reserved1, long reserved2, int instanceSize, Constant[] constants, Static[] statics, InstanceField[] instanceFields) { System.out.println("Class Dump:"); System.out.println(" class object id: " + classObjId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" super class object id: " + superClassObjId); System.out.println(" class loader object id: " + classLoaderObjId); System.out.println(" signer's object id: " + signersObjId); System.out.println(" protection domain object id: " + protectionDomainObjId); System.out.println(" reserved 1: " + reserved1); System.out.println(" reserved 2: " + reserved2); System.out.println(" instance size: " + instanceSize); System.out.println(" constant pool:"); for (Constant c: constants) { System.out.println(" " + c.constantPoolIndex + ": " + c.value); } System.out.println(" static fields:"); for (Static s: statics) { System.out.println(" " + stringMap.get(s.staticFieldNameStringId) + ": " + s.value); } System.out.println(" instance fields:"); for (InstanceField i: instanceFields) { System.out.println(" " + stringMap.get(i.fieldNameStringId) + ": " + i.type); } // store class info in a hashmap for later access classMap.put(classObjId, new ClassInfo(classObjId, superClassObjId, instanceSize, instanceFields)); } @Override public void instanceDump(long objId, int stackTraceSerialNum, long classObjId, Value<?>[] instanceFieldValues) { System.out.println("Instance Dump:"); System.out.println(" object id: " + objId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" class object id: " + classObjId); if (instanceFieldValues.length > 0) { System.out.println(" instance field values:"); // superclass of Object is 0 int i = 0; long nextClass = classObjId; while (nextClass != 0) { ClassInfo ci = classMap.get(nextClass); nextClass = ci.superClassObjId; for (InstanceField field : ci.instanceFields) { System.out.print(" " + stringMap.get(field.fieldNameStringId)); System.out.println(" = " + instanceFieldValues[i]); i++; } } assert i == instanceFieldValues.length; } } @Override public void objArrayDump(long objId, int stackTraceSerialNum, long elemClassObjId, long[] elems) { System.out.println("Object Array Dump:"); System.out.println(" object id: " + objId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.println(" element class object id: " + elemClassObjId); for (int i=0; i<elems.length; i++) { System.out.println(" element " + (i+1) + ": " + elems[i]); } } @Override public void primArrayDump(long objId, int stackTraceSerialNum, byte elemType, Value<?>[] elems) { System.out.println("Primitive Array Dump:"); System.out.println(" object id: " + objId); System.out.println(" stack trace serial num: " + stackTraceSerialNum); System.out.print(" number of elements: "); System.out.println(elems.length); System.out.println(" element type: " + getBasicType(elemType)); for (int i=0; i<elems.length; i++) { System.out.println(" element " + (i+1) + ": " + elems[i]); } } /* Utility methods */ private static boolean testBitMask(int bitMaskFlags, int mask) { if ((bitMaskFlags & mask) != 0) return true; else return false; } private static String getBasicType(byte type) { switch (type) { case 2: return "object"; case 4: return "boolean"; case 5: return "char"; case 6: return "float"; case 7: return "double"; case 8: return "byte"; case 9: return "short"; case 10: return "int"; case 11: return "long"; default: return null; } } private static String millisecondsDateToString(long milliseconds) { SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS"); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(milliseconds); return formatter.format(calendar.getTime()); } }