HandleHeappublic final class HandleHeap extends ChunkHandler Handle heap status updates. |
Fields Summary |
---|
public static final int | CHUNK_HPIF | public static final int | CHUNK_HPST | public static final int | CHUNK_HPEN | public static final int | CHUNK_HPSG | public static final int | CHUNK_HPGC | public static final int | CHUNK_REAE | public static final int | CHUNK_REAQ | public static final int | CHUNK_REAL | public static final int | WHEN_DISABLE | public static final int | WHEN_GC | public static final int | WHAT_MERGE | public static final int | WHAT_OBJ | public static final int | HPIF_WHEN_NEVER | public static final int | HPIF_WHEN_NOW | public static final int | HPIF_WHEN_NEXT_GC | public static final int | HPIF_WHEN_EVERY_GC | private static final HandleHeap | mInst |
Constructors Summary |
---|
private HandleHeap()
|
Methods Summary |
---|
public void | clientDisconnected(Client client)Client went away.
| public void | clientReady(Client client)Client is ready.
if (client.isHeapUpdateEnabled()) {
//sendHPSG(client, WHEN_GC, WHAT_MERGE);
sendHPIF(client, HPIF_WHEN_EVERY_GC);
}
| private java.lang.String | descriptorToDot(java.lang.String str)Converts a VM class descriptor string ("Landroid/os/Debug;") to
a dot-notation class name ("android.os.Debug").
// count the number of arrays.
int array = 0;
while (str.startsWith("[")) {
str = str.substring(1);
array++;
}
int len = str.length();
/* strip off leading 'L' and trailing ';' if appropriate */
if (len >= 2 && str.charAt(0) == 'L" && str.charAt(len - 1) == ';") {
str = str.substring(1, len-1);
str = str.replace('/", '.");
} else {
// convert the basic types
if ("C".equals(str)) {
str = "char";
} else if ("B".equals(str)) {
str = "byte";
} else if ("Z".equals(str)) {
str = "boolean";
} else if ("S".equals(str)) {
str = "short";
} else if ("I".equals(str)) {
str = "int";
} else if ("J".equals(str)) {
str = "long";
} else if ("F".equals(str)) {
str = "float";
} else if ("D".equals(str)) {
str = "double";
}
}
// now add the array part
for (int a = 0 ; a < array; a++) {
str = str + "[]";
}
return str;
| private static void | dumpRecords(AllocationInfo[] records)
System.out.println("Found " + records.length + " records:");
for (AllocationInfo rec: records) {
System.out.println("tid=" + rec.getThreadId() + " "
+ rec.getAllocatedClass() + " (" + rec.getSize() + " bytes)");
for (StackTraceElement ste: rec.getStackTrace()) {
if (ste.isNativeMethod()) {
System.out.println(" " + ste.getClassName()
+ "." + ste.getMethodName()
+ " (Native method)");
} else {
System.out.println(" " + ste.getClassName()
+ "." + ste.getMethodName()
+ " (" + ste.getFileName()
+ ":" + ste.getLineNumber() + ")");
}
}
}
| public void | handleChunk(Client client, int type, java.nio.ByteBuffer data, boolean isReply, int msgId)Chunk handler entry point.
Log.d("ddm-heap", "handling " + ChunkHandler.name(type));
if (type == CHUNK_HPIF) {
handleHPIF(client, data);
client.update(Client.CHANGE_HEAP_DATA);
} else if (type == CHUNK_HPST) {
handleHPST(client, data);
} else if (type == CHUNK_HPEN) {
handleHPEN(client, data);
client.update(Client.CHANGE_HEAP_DATA);
} else if (type == CHUNK_HPSG) {
handleHPSG(client, data);
} else if (type == CHUNK_REAQ) {
handleREAQ(client, data);
client.update(Client.CHANGE_HEAP_ALLOCATION_STATUS);
} else if (type == CHUNK_REAL) {
handleREAL(client, data);
client.update(Client.CHANGE_HEAP_ALLOCATIONS);
} else {
handleUnknownChunk(client, type, data, isReply, msgId);
}
| private void | handleHPEN(Client client, java.nio.ByteBuffer data)
/* Let the UI know that we've received all of the
* data for this heap.
*/
//xxx todo: only seal data that belongs to the heap mentioned in <data>.
client.getClientData().getVmHeapData().sealHeapData();
| private void | handleHPIF(Client client, java.nio.ByteBuffer data)
Log.d("ddm-heap", "HPIF!");
try {
int numHeaps = data.getInt();
for (int i = 0; i < numHeaps; i++) {
int heapId = data.getInt();
@SuppressWarnings("unused")
long timeStamp = data.getLong();
@SuppressWarnings("unused")
byte reason = data.get();
long maxHeapSize = (long)data.getInt() & 0x00ffffffff;
long heapSize = (long)data.getInt() & 0x00ffffffff;
long bytesAllocated = (long)data.getInt() & 0x00ffffffff;
long objectsAllocated = (long)data.getInt() & 0x00ffffffff;
client.getClientData().setHeapInfo(heapId, maxHeapSize,
heapSize, bytesAllocated, objectsAllocated);
}
} catch (BufferUnderflowException ex) {
Log.w("ddm-heap", "malformed HPIF chunk from client");
}
| private void | handleHPSG(Client client, java.nio.ByteBuffer data)
byte dataCopy[] = new byte[data.limit()];
data.rewind();
data.get(dataCopy);
data = ByteBuffer.wrap(dataCopy);
client.getClientData().getVmHeapData().addHeapData(data);
//xxx todo: add to the heap mentioned in <data>
| private void | handleHPST(Client client, java.nio.ByteBuffer data)
/* Clear out any data that's sitting around to
* get ready for the chunks that are about to come.
*/
//xxx todo: only clear data that belongs to the heap mentioned in <data>.
client.getClientData().getVmHeapData().clearHeapData();
| private void | handleREAL(Client client, java.nio.ByteBuffer data)
Log.e("ddm-heap", "*** Received " + name(CHUNK_REAL));
int messageHdrLen, entryHdrLen, stackFrameLen;
int numEntries, offsetToStrings;
int numClassNames, numMethodNames, numFileNames;
/*
* Read the header.
*/
messageHdrLen = (data.get() & 0xff);
entryHdrLen = (data.get() & 0xff);
stackFrameLen = (data.get() & 0xff);
numEntries = (data.getShort() & 0xffff);
offsetToStrings = data.getInt();
numClassNames = (data.getShort() & 0xffff);
numMethodNames = (data.getShort() & 0xffff);
numFileNames = (data.getShort() & 0xffff);
/*
* Skip forward to the strings and read them.
*/
data.position(offsetToStrings);
String[] classNames = new String[numClassNames];
String[] methodNames = new String[numMethodNames];
String[] fileNames = new String[numFileNames];
readStringTable(data, classNames);
readStringTable(data, methodNames);
//System.out.println("METHODS: "
// + java.util.Arrays.deepToString(methodNames));
readStringTable(data, fileNames);
/*
* Skip back to a point just past the header and start reading
* entries.
*/
data.position(messageHdrLen);
ArrayList<AllocationInfo> list = new ArrayList<AllocationInfo>(numEntries);
for (int i = 0; i < numEntries; i++) {
int totalSize;
int threadId, classNameIndex, stackDepth;
totalSize = data.getInt();
threadId = (data.getShort() & 0xffff);
classNameIndex = (data.getShort() & 0xffff);
stackDepth = (data.get() & 0xff);
/* we've consumed 9 bytes; gobble up any extra */
for (int skip = 9; skip < entryHdrLen; skip++)
data.get();
StackTraceElement[] steArray = new StackTraceElement[stackDepth];
/*
* Pull out the stack trace.
*/
for (int sti = 0; sti < stackDepth; sti++) {
int methodClassNameIndex, methodNameIndex;
int methodSourceFileIndex;
short lineNumber;
String methodClassName, methodName, methodSourceFile;
methodClassNameIndex = (data.getShort() & 0xffff);
methodNameIndex = (data.getShort() & 0xffff);
methodSourceFileIndex = (data.getShort() & 0xffff);
lineNumber = data.getShort();
methodClassName = classNames[methodClassNameIndex];
methodName = methodNames[methodNameIndex];
methodSourceFile = fileNames[methodSourceFileIndex];
steArray[sti] = new StackTraceElement(methodClassName,
methodName, methodSourceFile, lineNumber);
/* we've consumed 8 bytes; gobble up any extra */
for (int skip = 9; skip < stackFrameLen; skip++)
data.get();
}
list.add(new AllocationInfo(classNames[classNameIndex],
totalSize, (short) threadId, steArray));
}
// sort biggest allocations first.
Collections.sort(list);
client.getClientData().setAllocations(list.toArray(new AllocationInfo[numEntries]));
| private void | handleREAQ(Client client, java.nio.ByteBuffer data)
boolean enabled;
enabled = (data.get() != 0);
Log.d("ddm-heap", "REAQ says: enabled=" + enabled);
client.getClientData().setAllocationStatus(enabled);
| private void | readStringTable(java.nio.ByteBuffer data, java.lang.String[] strings)Reads a string table out of "data".
This is just a serial collection of strings, each of which is a
four-byte length followed by UTF-16 data.
int count = strings.length;
int i;
for (i = 0; i < count; i++) {
int nameLen = data.getInt();
String descriptor = getString(data, nameLen);
strings[i] = descriptorToDot(descriptor);
}
| public static void | register(MonitorThread mt)Register for the packets we expect to get from the client.
mt.registerChunkHandler(CHUNK_HPIF, mInst);
mt.registerChunkHandler(CHUNK_HPST, mInst);
mt.registerChunkHandler(CHUNK_HPEN, mInst);
mt.registerChunkHandler(CHUNK_HPSG, mInst);
mt.registerChunkHandler(CHUNK_REAQ, mInst);
mt.registerChunkHandler(CHUNK_REAL, mInst);
| public static void | sendHPGC(Client client)Sends an HPGC request to the client.
ByteBuffer rawBuf = allocBuffer(0);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
// no data
finishChunkPacket(packet, CHUNK_HPGC, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_HPGC));
client.sendAndConsume(packet, mInst);
| public static void | sendHPIF(Client client, int when)Send an HPIF (HeaP InFo) request to the client.
ByteBuffer rawBuf = allocBuffer(1);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
buf.put((byte)when);
finishChunkPacket(packet, CHUNK_HPIF, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_HPIF) + ": when=" + when);
client.sendAndConsume(packet, mInst);
| public static void | sendHPSG(Client client, int when, int what)Sends an HPSG (HeaP SeGment) request to the client.
ByteBuffer rawBuf = allocBuffer(2);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
buf.put((byte)when);
buf.put((byte)what);
finishChunkPacket(packet, CHUNK_HPSG, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_HPSG) + ": when="
+ when + ", what=" + what);
client.sendAndConsume(packet, mInst);
| public static void | sendREAE(Client client, boolean enable)Sends a REAE (REcent Allocation Enable) request to the client.
ByteBuffer rawBuf = allocBuffer(1);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
buf.put((byte) (enable ? 1 : 0));
finishChunkPacket(packet, CHUNK_REAE, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_REAE) + ": " + enable);
client.sendAndConsume(packet, mInst);
| public static void | sendREAL(Client client)Sends a REAL (REcent ALlocation) request to the client.
ByteBuffer rawBuf = allocBuffer(0);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
// no data
finishChunkPacket(packet, CHUNK_REAL, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_REAL));
client.sendAndConsume(packet, mInst);
| public static void | sendREAQ(Client client)Sends a REAQ (REcent Allocation Query) request to the client.
ByteBuffer rawBuf = allocBuffer(0);
JdwpPacket packet = new JdwpPacket(rawBuf);
ByteBuffer buf = getChunkDataBuf(rawBuf);
// no data
finishChunkPacket(packet, CHUNK_REAQ, buf.position());
Log.d("ddm-heap", "Sending " + name(CHUNK_REAQ));
client.sendAndConsume(packet, mInst);
|
|