403 lines
17 KiB
Java
403 lines
17 KiB
Java
package com.squareup.haha.perflib;
|
|
|
|
import com.squareup.haha.perflib.io.HprofBuffer;
|
|
import gnu.trove.TLongObjectHashMap;
|
|
import java.io.EOFException;
|
|
import java.io.IOException;
|
|
|
|
/* loaded from: classes.dex */
|
|
public class HprofParser {
|
|
private static final int ALLOC_SITES = 6;
|
|
private static final int CONTROL_SETTINGS = 14;
|
|
private static final int CPU_SAMPLES = 13;
|
|
private static final int END_THREAD = 11;
|
|
private static final int HEAP_DUMP = 12;
|
|
private static final int HEAP_DUMP_END = 44;
|
|
private static final int HEAP_DUMP_SEGMENT = 28;
|
|
private static final int HEAP_SUMMARY = 7;
|
|
private static final int LOAD_CLASS = 2;
|
|
private static final int ROOT_CLASS_DUMP = 32;
|
|
private static final int ROOT_DEBUGGER = 139;
|
|
private static final int ROOT_FINALIZING = 138;
|
|
private static final int ROOT_HEAP_DUMP_INFO = 254;
|
|
private static final int ROOT_INSTANCE_DUMP = 33;
|
|
private static final int ROOT_INTERNED_STRING = 137;
|
|
private static final int ROOT_JAVA_FRAME = 3;
|
|
private static final int ROOT_JNI_GLOBAL = 1;
|
|
private static final int ROOT_JNI_LOCAL = 2;
|
|
private static final int ROOT_JNI_MONITOR = 142;
|
|
private static final int ROOT_MONITOR_USED = 7;
|
|
private static final int ROOT_NATIVE_STACK = 4;
|
|
private static final int ROOT_OBJECT_ARRAY_DUMP = 34;
|
|
private static final int ROOT_PRIMITIVE_ARRAY_DUMP = 35;
|
|
private static final int ROOT_PRIMITIVE_ARRAY_NODATA = 195;
|
|
private static final int ROOT_REFERENCE_CLEANUP = 140;
|
|
private static final int ROOT_STICKY_CLASS = 5;
|
|
private static final int ROOT_THREAD_BLOCK = 6;
|
|
private static final int ROOT_THREAD_OBJECT = 8;
|
|
private static final int ROOT_UNKNOWN = 255;
|
|
private static final int ROOT_UNREACHABLE = 144;
|
|
private static final int ROOT_VM_INTERNAL = 141;
|
|
private static final int STACK_FRAME = 4;
|
|
private static final int STACK_TRACE = 5;
|
|
private static final int START_THREAD = 10;
|
|
private static final int STRING_IN_UTF8 = 1;
|
|
private static final int UNLOAD_CLASS = 3;
|
|
int mIdSize;
|
|
private final HprofBuffer mInput;
|
|
Snapshot mSnapshot;
|
|
TLongObjectHashMap<String> mStrings = new TLongObjectHashMap<>();
|
|
TLongObjectHashMap<String> mClassNames = new TLongObjectHashMap<>();
|
|
|
|
public HprofParser(HprofBuffer hprofBuffer) {
|
|
this.mInput = hprofBuffer;
|
|
}
|
|
|
|
private int loadBasicObj(RootType rootType) throws IOException {
|
|
this.mSnapshot.addRoot(new RootObj(rootType, readId()));
|
|
return this.mIdSize;
|
|
}
|
|
|
|
private void loadClass() throws IOException {
|
|
this.mInput.readInt();
|
|
long readId = readId();
|
|
this.mInput.readInt();
|
|
this.mClassNames.put(readId, this.mStrings.get(readId()));
|
|
}
|
|
|
|
private int loadClassDump() throws IOException {
|
|
long readId = readId();
|
|
StackTrace stackTrace = this.mSnapshot.getStackTrace(this.mInput.readInt());
|
|
long readId2 = readId();
|
|
long readId3 = readId();
|
|
readId();
|
|
readId();
|
|
readId();
|
|
readId();
|
|
int readInt = this.mInput.readInt();
|
|
int i = (this.mIdSize * 7) + 4 + 4;
|
|
int readUnsignedShort = readUnsignedShort();
|
|
int i2 = i + 2;
|
|
for (int i3 = 0; i3 < readUnsignedShort; i3++) {
|
|
readUnsignedShort();
|
|
i2 += skipValue() + 2;
|
|
}
|
|
ClassObj classObj = new ClassObj(readId, stackTrace, this.mClassNames.get(readId), this.mInput.position());
|
|
classObj.setSuperClassId(readId2);
|
|
classObj.setClassLoaderId(readId3);
|
|
int readUnsignedShort2 = readUnsignedShort();
|
|
int i4 = i2 + 2;
|
|
Field[] fieldArr = new Field[readUnsignedShort2];
|
|
for (int i5 = 0; i5 < readUnsignedShort2; i5++) {
|
|
String str = this.mStrings.get(readId());
|
|
Type type = Type.getType(this.mInput.readByte());
|
|
fieldArr[i5] = new Field(type, str);
|
|
skipFully(this.mSnapshot.getTypeSize(type));
|
|
i4 += this.mIdSize + 1 + this.mSnapshot.getTypeSize(type);
|
|
}
|
|
classObj.setStaticFields(fieldArr);
|
|
int readUnsignedShort3 = readUnsignedShort();
|
|
int i6 = i4 + 2;
|
|
Field[] fieldArr2 = new Field[readUnsignedShort3];
|
|
for (int i7 = 0; i7 < readUnsignedShort3; i7++) {
|
|
fieldArr2[i7] = new Field(Type.getType(readUnsignedByte()), this.mStrings.get(readId()));
|
|
i6 += this.mIdSize + 1;
|
|
}
|
|
classObj.setFields(fieldArr2);
|
|
classObj.setInstanceSize(readInt);
|
|
this.mSnapshot.addClass(readId, classObj);
|
|
return i6;
|
|
}
|
|
|
|
private void loadHeapDump(long j) throws IOException {
|
|
int loadBasicObj;
|
|
while (j > 0) {
|
|
int readUnsignedByte = readUnsignedByte();
|
|
long j2 = j - 1;
|
|
if (readUnsignedByte == ROOT_UNREACHABLE) {
|
|
loadBasicObj = loadBasicObj(RootType.UNREACHABLE);
|
|
} else {
|
|
if (readUnsignedByte == ROOT_PRIMITIVE_ARRAY_NODATA) {
|
|
System.err.println("+--- PRIMITIVE ARRAY NODATA DUMP");
|
|
loadPrimitiveArrayDump();
|
|
throw new IllegalArgumentException("Don't know how to load a nodata array");
|
|
}
|
|
if (readUnsignedByte == ROOT_HEAP_DUMP_INFO) {
|
|
this.mSnapshot.setHeapTo(this.mInput.readInt(), this.mStrings.get(readId()));
|
|
loadBasicObj = this.mIdSize + 4;
|
|
} else if (readUnsignedByte != ROOT_UNKNOWN) {
|
|
switch (readUnsignedByte) {
|
|
case 1:
|
|
j2 -= loadBasicObj(RootType.NATIVE_STATIC);
|
|
readId();
|
|
loadBasicObj = this.mIdSize;
|
|
break;
|
|
case 2:
|
|
loadBasicObj = loadJniLocal();
|
|
break;
|
|
case 3:
|
|
loadBasicObj = loadJavaFrame();
|
|
break;
|
|
case 4:
|
|
loadBasicObj = loadNativeStack();
|
|
break;
|
|
case 5:
|
|
loadBasicObj = loadBasicObj(RootType.SYSTEM_CLASS);
|
|
break;
|
|
case 6:
|
|
loadBasicObj = loadThreadBlock();
|
|
break;
|
|
case 7:
|
|
loadBasicObj = loadBasicObj(RootType.BUSY_MONITOR);
|
|
break;
|
|
case 8:
|
|
loadBasicObj = loadThreadObject();
|
|
break;
|
|
default:
|
|
switch (readUnsignedByte) {
|
|
case 32:
|
|
loadBasicObj = loadClassDump();
|
|
break;
|
|
case 33:
|
|
loadBasicObj = loadInstanceDump();
|
|
break;
|
|
case 34:
|
|
loadBasicObj = loadObjectArrayDump();
|
|
break;
|
|
case 35:
|
|
loadBasicObj = loadPrimitiveArrayDump();
|
|
break;
|
|
default:
|
|
switch (readUnsignedByte) {
|
|
case ROOT_INTERNED_STRING /* 137 */:
|
|
loadBasicObj = loadBasicObj(RootType.INTERNED_STRING);
|
|
break;
|
|
case ROOT_FINALIZING /* 138 */:
|
|
loadBasicObj = loadBasicObj(RootType.FINALIZING);
|
|
break;
|
|
case ROOT_DEBUGGER /* 139 */:
|
|
loadBasicObj = loadBasicObj(RootType.DEBUGGER);
|
|
break;
|
|
case 140:
|
|
loadBasicObj = loadBasicObj(RootType.REFERENCE_CLEANUP);
|
|
break;
|
|
case ROOT_VM_INTERNAL /* 141 */:
|
|
loadBasicObj = loadBasicObj(RootType.VM_INTERNAL);
|
|
break;
|
|
case ROOT_JNI_MONITOR /* 142 */:
|
|
loadBasicObj = loadJniMonitor();
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("loadHeapDump loop with unknown tag " + readUnsignedByte + " with " + this.mInput.remaining() + " bytes possibly remaining");
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
loadBasicObj = loadBasicObj(RootType.UNKNOWN);
|
|
}
|
|
}
|
|
j = j2 - loadBasicObj;
|
|
}
|
|
}
|
|
|
|
private int loadInstanceDump() throws IOException {
|
|
long readId = readId();
|
|
StackTrace stackTrace = this.mSnapshot.getStackTrace(this.mInput.readInt());
|
|
long readId2 = readId();
|
|
int readInt = this.mInput.readInt();
|
|
ClassInstance classInstance = new ClassInstance(readId, stackTrace, this.mInput.position());
|
|
classInstance.setClassId(readId2);
|
|
this.mSnapshot.addInstance(readId, classInstance);
|
|
skipFully(readInt);
|
|
int i = this.mIdSize;
|
|
return i + 4 + i + 4 + readInt;
|
|
}
|
|
|
|
private int loadJavaFrame() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addRoot(new RootObj(RootType.JAVA_LOCAL, readId, readInt, this.mSnapshot.getStackTraceAtDepth(this.mSnapshot.getThread(readInt).mStackTrace, this.mInput.readInt())));
|
|
return this.mIdSize + 4 + 4;
|
|
}
|
|
|
|
private int loadJniLocal() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addRoot(new RootObj(RootType.NATIVE_LOCAL, readId, readInt, this.mSnapshot.getStackTraceAtDepth(this.mSnapshot.getThread(readInt).mStackTrace, this.mInput.readInt())));
|
|
return this.mIdSize + 4 + 4;
|
|
}
|
|
|
|
private int loadJniMonitor() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addRoot(new RootObj(RootType.NATIVE_MONITOR, readId, readInt, this.mSnapshot.getStackTraceAtDepth(this.mSnapshot.getThread(readInt).mStackTrace, this.mInput.readInt())));
|
|
return this.mIdSize + 4 + 4;
|
|
}
|
|
|
|
private int loadNativeStack() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addRoot(new RootObj(RootType.NATIVE_STACK, readId, readInt, this.mSnapshot.getStackTrace(this.mSnapshot.getThread(readInt).mStackTrace)));
|
|
return this.mIdSize + 4;
|
|
}
|
|
|
|
private int loadObjectArrayDump() throws IOException {
|
|
long readId = readId();
|
|
StackTrace stackTrace = this.mSnapshot.getStackTrace(this.mInput.readInt());
|
|
int readInt = this.mInput.readInt();
|
|
long readId2 = readId();
|
|
ArrayInstance arrayInstance = new ArrayInstance(readId, stackTrace, Type.OBJECT, readInt, this.mInput.position());
|
|
arrayInstance.setClassId(readId2);
|
|
this.mSnapshot.addInstance(readId, arrayInstance);
|
|
int i = readInt * this.mIdSize;
|
|
skipFully(i);
|
|
int i2 = this.mIdSize;
|
|
return i2 + 4 + 4 + i2 + i;
|
|
}
|
|
|
|
private int loadPrimitiveArrayDump() throws IOException {
|
|
long readId = readId();
|
|
StackTrace stackTrace = this.mSnapshot.getStackTrace(this.mInput.readInt());
|
|
int readInt = this.mInput.readInt();
|
|
Type type = Type.getType(readUnsignedByte());
|
|
int typeSize = this.mSnapshot.getTypeSize(type);
|
|
this.mSnapshot.addInstance(readId, new ArrayInstance(readId, stackTrace, type, readInt, this.mInput.position()));
|
|
int i = readInt * typeSize;
|
|
skipFully(i);
|
|
return this.mIdSize + 4 + 4 + 1 + i;
|
|
}
|
|
|
|
private void loadStackFrame() throws IOException {
|
|
this.mSnapshot.addStackFrame(new StackFrame(readId(), this.mStrings.get(readId()), this.mStrings.get(readId()), this.mStrings.get(readId()), this.mInput.readInt(), this.mInput.readInt()));
|
|
}
|
|
|
|
private void loadStackTrace() throws IOException {
|
|
int readInt = this.mInput.readInt();
|
|
int readInt2 = this.mInput.readInt();
|
|
int readInt3 = this.mInput.readInt();
|
|
StackFrame[] stackFrameArr = new StackFrame[readInt3];
|
|
for (int i = 0; i < readInt3; i++) {
|
|
stackFrameArr[i] = this.mSnapshot.getStackFrame(readId());
|
|
}
|
|
this.mSnapshot.addStackTrace(new StackTrace(readInt, readInt2, stackFrameArr));
|
|
}
|
|
|
|
private void loadString(int i) throws IOException {
|
|
this.mStrings.put(readId(), readUTF8(i));
|
|
}
|
|
|
|
private int loadThreadBlock() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addRoot(new RootObj(RootType.THREAD_BLOCK, readId, readInt, this.mSnapshot.getStackTrace(this.mSnapshot.getThread(readInt).mStackTrace)));
|
|
return this.mIdSize + 4;
|
|
}
|
|
|
|
private int loadThreadObject() throws IOException {
|
|
long readId = readId();
|
|
int readInt = this.mInput.readInt();
|
|
this.mSnapshot.addThread(new ThreadObj(readId, this.mInput.readInt()), readInt);
|
|
return this.mIdSize + 4 + 4;
|
|
}
|
|
|
|
private long readId() throws IOException {
|
|
int i = this.mIdSize;
|
|
if (i == 1) {
|
|
return this.mInput.readByte();
|
|
}
|
|
if (i == 2) {
|
|
return this.mInput.readShort();
|
|
}
|
|
if (i == 4) {
|
|
return this.mInput.readInt();
|
|
}
|
|
if (i == 8) {
|
|
return this.mInput.readLong();
|
|
}
|
|
throw new IllegalArgumentException("ID Length must be 1, 2, 4, or 8");
|
|
}
|
|
|
|
private String readNullTerminatedString() throws IOException {
|
|
StringBuilder sb = new StringBuilder();
|
|
while (true) {
|
|
byte readByte = this.mInput.readByte();
|
|
if (readByte == 0) {
|
|
return sb.toString();
|
|
}
|
|
sb.append((char) readByte);
|
|
}
|
|
}
|
|
|
|
private String readUTF8(int i) throws IOException {
|
|
byte[] bArr = new byte[i];
|
|
this.mInput.read(bArr);
|
|
return new String(bArr, "utf-8");
|
|
}
|
|
|
|
private int readUnsignedByte() throws IOException {
|
|
return this.mInput.readByte() & 255;
|
|
}
|
|
|
|
private long readUnsignedInt() throws IOException {
|
|
return this.mInput.readInt() & 4294967295L;
|
|
}
|
|
|
|
private int readUnsignedShort() throws IOException {
|
|
return this.mInput.readShort() & 65535;
|
|
}
|
|
|
|
private void skipFully(long j) throws IOException {
|
|
HprofBuffer hprofBuffer = this.mInput;
|
|
hprofBuffer.setPosition(hprofBuffer.position() + j);
|
|
}
|
|
|
|
private int skipValue() throws IOException {
|
|
int typeSize = this.mSnapshot.getTypeSize(Type.getType(readUnsignedByte()));
|
|
skipFully(typeSize);
|
|
return typeSize + 1;
|
|
}
|
|
|
|
public final Snapshot parse() {
|
|
Snapshot snapshot = new Snapshot(this.mInput);
|
|
this.mSnapshot = snapshot;
|
|
try {
|
|
try {
|
|
readNullTerminatedString();
|
|
this.mIdSize = this.mInput.readInt();
|
|
this.mSnapshot.setIdSize(this.mIdSize);
|
|
this.mInput.readLong();
|
|
while (this.mInput.hasRemaining()) {
|
|
int readUnsignedByte = readUnsignedByte();
|
|
this.mInput.readInt();
|
|
long readUnsignedInt = readUnsignedInt();
|
|
if (readUnsignedByte == 1) {
|
|
loadString(((int) readUnsignedInt) - this.mIdSize);
|
|
} else if (readUnsignedByte == 2) {
|
|
loadClass();
|
|
} else if (readUnsignedByte == 4) {
|
|
loadStackFrame();
|
|
} else if (readUnsignedByte == 5) {
|
|
loadStackTrace();
|
|
} else if (readUnsignedByte == 12) {
|
|
loadHeapDump(readUnsignedInt);
|
|
this.mSnapshot.setToDefaultHeap();
|
|
} else if (readUnsignedByte != 28) {
|
|
skipFully(readUnsignedInt);
|
|
} else {
|
|
loadHeapDump(readUnsignedInt);
|
|
this.mSnapshot.setToDefaultHeap();
|
|
}
|
|
}
|
|
} catch (EOFException unused) {
|
|
}
|
|
this.mSnapshot.resolveClasses();
|
|
this.mSnapshot.resolveReferences();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
this.mClassNames.clear();
|
|
this.mStrings.clear();
|
|
return snapshot;
|
|
}
|
|
}
|