/*******************************************************************************
* 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 org.apache.kato.hprof;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.kato.hprof.datalayer.HProfFactory;
import org.apache.kato.hprof.datalayer.HProfFile;
import org.apache.kato.hprof.datalayer.IControlSettingsHProfRecord;
import org.apache.kato.hprof.datalayer.IHProfRecord;
import org.apache.kato.hprof.datalayer.IHeapDumpHProfRecord;
import org.apache.kato.hprof.datalayer.IJavaStackFrameHProfRecord;
import org.apache.kato.hprof.datalayer.IJavaStackTraceHProfRecord;
import org.apache.kato.hprof.datalayer.ILoadClassHProfRecord;
import org.apache.kato.hprof.datalayer.IUTF8HProfRecord;
public class HPROFFormattedReporter {
private PrintStream out=System.out;
private Map<Integer,Counter> stats=new TreeMap<Integer,Counter>();
private TreeSet<String> labels=new TreeSet<String>();
/**
* @param args
*/
public static void main(String[] args) {
//File dump=new File("C:/Documents and Settings/spoole/workspace/HProf Binary Format Reader/data/java.hprof");
HPROFFormattedReporter reporter=new HPROFFormattedReporter();
File hprofFile=new File(args[0]);
try {
reporter.report(hprofFile);
} catch (IOException e) {
e.printStackTrace();
}
}
public void report(File dump) throws IOException {
HProfFile h=HProfFactory.createReader(dump);
h.open();
String header=h.getHeader();
int idSize=h.getIdentifierSize();
long timeStamp=h.getTimeStamp();
out.println("HPROF : "+header);
out.println("ID SIZE : "+idSize);
out.println("TIMESTAMP: "+timeStamp);
int counter=0;
while(true) {
IHProfRecord record=h.getRecord(counter);
if(record==null) break;
report(record);
counter++;
}
reportStats();
out.println("Report completed. "+counter+" records");
h.close();
}
private void reportStats() {
for(Integer i:stats.keySet()) {
Counter c=stats.get(i);
out.println("tag "+Integer.toHexString(i)+" occurs "+c.count+" time(s)");
}
}
private void report(IHProfRecord record) {
int tag=record.getTag();
accumulateStatistics(tag);
out.println("----------------------------------------- "+toHex(tag)+":"+record.getDataLength());
switch(tag) {
case 0x01: IUTF8HProfRecord utf8Record=(IUTF8HProfRecord)record;
reportUTF8(utf8Record);
break;
case 0x02: ILoadClassHProfRecord loadClass=(ILoadClassHProfRecord)record;
reportLoadClass(loadClass);
break;
case 0x04: IJavaStackFrameHProfRecord frameRecord=(IJavaStackFrameHProfRecord)record;
reportFrameRecord(frameRecord);
break;
case 0x05: IJavaStackTraceHProfRecord traceRecord=(IJavaStackTraceHProfRecord)record;
reportTraceRecord(traceRecord);
break;
case 0x0C: IHeapDumpHProfRecord dumpRecord = (IHeapDumpHProfRecord)record;
reportHeapDump(dumpRecord);
break;
case 0x0E: IControlSettingsHProfRecord settings=(IControlSettingsHProfRecord) record;
reportSettings(settings);
break;
}
}
private void reportFrameRecord(IJavaStackFrameHProfRecord record) {
out.println("frame - stack frame id :"+toHex(record.getStackFrameID()));
out.println("frame - method name id :"+toHex(record.getMethodNameID()));
out.println("frame - method signature id :"+toHex(record.getMethodSignatureID()));
out.println("frame - source file name id :"+toHex(record.getSourceFileNameID()));
out.println("frame - class serial number :"+record.getClassSerialNumber());
out.println("frame - line number :"+record.getLineNumber());
}
private String toHex(long h) {
return HProfRecordFormatter.toHex(h);
}
private void reportLoadClass(ILoadClassHProfRecord loadClass) {
out.println("load class - class serial number : "+loadClass.getClassSerialNumber());
out.println("load class - object ID : "+toHex(loadClass.getClassObjectID()));
out.println("load class - stack trace serial number : "+loadClass.getStackTraceSerialNumber());
out.println("load class - class Name ID : "+toHex(loadClass.getClassNameID()));
}
private void reportUTF8(IUTF8HProfRecord utf8Record) {
try {
String label=new String(utf8Record.getCharacters(),"UTF-8");
if(labels.contains(label)) {
int a=1;
}
out.println("utf8 record id: "+toHex(utf8Record.getNameID())+" data: ["+label+"]");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void reportTraceRecord(IJavaStackTraceHProfRecord traceRecord) {
out.println("stack trace serial number: "+traceRecord.getSerialNumber());
out.println("frame count: "+traceRecord.getFrameCount());
}
private void reportHeapDump(IHeapDumpHProfRecord dumpRecord) {
out.println("dump record");
int index=0;
while(true) {
Object record=dumpRecord.getSubRecord(index);
if(record==null) break;
out.println(">>"+record);
index++;
}
}
private void accumulateStatistics(int tag) {
Counter c=null;
if(stats.containsKey(tag)) {
c=stats.get(tag);
}
else {
c=new Counter();
stats.put(tag,c);
}
c.count++;
}
private void reportSettings(IControlSettingsHProfRecord settings) {
out.println("Is AllocTrace:"+settings.isAllocTrace());
out.println("Is CPUSampling:"+settings.isCpuSampling());
out.println("Stack Trace Depth:"+settings.getStackTraceDepth());
}
public HPROFFormattedReporter() {
}
class Counter {
int count=0;
}
}