aboutsummaryrefslogtreecommitdiffstats
path: root/ddms
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2010-01-29 13:12:54 -0800
committerAndy McFadden <fadden@android.com>2010-01-29 13:18:27 -0800
commit7b5d6e7b8b298b2a65b312561efb67f2316f1f16 (patch)
tree06c4f511fbef409ab3d70b11710066bc93ed8342 /ddms
parent9414b2eef9dfae49c28149e61e4105850f934159 (diff)
downloadsdk-7b5d6e7b8b298b2a65b312561efb67f2316f1f16.zip
sdk-7b5d6e7b8b298b2a65b312561efb67f2316f1f16.tar.gz
sdk-7b5d6e7b8b298b2a65b312561efb67f2316f1f16.tar.bz2
Strawman support for streaming hprof dumps.
Send an HPDS instead of HPDU when the client VM supports it. Once additional support is added to DDMS, this will allow grabbing an hprof dump through DDMS even if the target app doesn't have permission to write to /sdcard. (The down side is that the dump must be held on the native heap while it's generated, temporarily bloating the process by a few megabytes.) For bug 2092855.
Diffstat (limited to 'ddms')
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/Client.java11
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java6
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java36
3 files changed, 50 insertions, 3 deletions
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java b/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
index efa47d7..fa53bef 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
@@ -230,10 +230,15 @@ public class Client {
* Makes the VM dump an HPROF file
*/
public void dumpHprof() {
+ boolean canStream = false; //mClientData.hasFeature(ClientData.FEATURE_HPROF_STREAMING);
try {
- String file = "/sdcard/" + mClientData.getClientDescription().replaceAll("\\:.*", "") +
- ".hprof";
- HandleHeap.sendHPDU(this, file);
+ if (canStream) {
+ HandleHeap.sendHPDS(this);
+ } else {
+ String file = "/sdcard/" + mClientData.getClientDescription().replaceAll("\\:.*", "") +
+ ".hprof";
+ HandleHeap.sendHPDU(this, file);
+ }
} catch (IOException e) {
Log.w("ddms", "Send of HPDU message failed");
// ignore
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java b/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
index eca0be4..d5fe2d5 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java
@@ -136,6 +136,12 @@ public class ClientData {
*/
public final static String FEATURE_HPROF = "hprof-heap-dump"; // $NON-NLS-1$
+ /**
+ * String for feature allowing direct streaming of hprof dumps
+ * @see #hasFeature(String)
+ */
+ public final static String FEATURE_HPROF_STREAMING = "hprof-heap-dump-streaming"; // $NON-NLS-1$
+
private static IHprofDumpHandler sHprofDumpHandler;
private static IMethodProfilingHandler sMethodProfilingHandler;
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java b/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
index 23050af..f3f5497 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
@@ -36,6 +36,7 @@ final class HandleHeap extends ChunkHandler {
public static final int CHUNK_HPSG = type("HPSG");
public static final int CHUNK_HPGC = type("HPGC");
public static final int CHUNK_HPDU = type("HPDU");
+ public static final int CHUNK_HPDS = type("HPDS");
public static final int CHUNK_REAE = type("REAE");
public static final int CHUNK_REAQ = type("REAQ");
public static final int CHUNK_REAL = type("REAL");
@@ -64,6 +65,7 @@ final class HandleHeap extends ChunkHandler {
mt.registerChunkHandler(CHUNK_HPST, mInst);
mt.registerChunkHandler(CHUNK_HPEN, mInst);
mt.registerChunkHandler(CHUNK_HPSG, mInst);
+ mt.registerChunkHandler(CHUNK_HPDS, mInst);
mt.registerChunkHandler(CHUNK_REAQ, mInst);
mt.registerChunkHandler(CHUNK_REAL, mInst);
}
@@ -102,6 +104,8 @@ final class HandleHeap extends ChunkHandler {
handleHPSG(client, data);
} else if (type == CHUNK_HPDU) {
handleHPDU(client, data);
+ } else if (type == CHUNK_HPDS) {
+ handleHPDS(client, data);
} else if (type == CHUNK_REAQ) {
handleREAQ(client, data);
} else if (type == CHUNK_REAL) {
@@ -247,6 +251,30 @@ final class HandleHeap extends ChunkHandler {
client.getClientData().setPendingHprofDump(fileName);
}
+ /**
+ * Sends an HPDS request to the client.
+ *
+ * We will get an HPDS response when the heap dump has completed. On
+ * failure we get a generic failure response.
+ *
+ * This is more expensive for the device than HPDU, because the entire
+ * heap dump is held in RAM instead of spooled out to a temp file. On
+ * the other hand, permission to write to /sdcard is not required.
+ *
+ * @param fileName name of output file (on device)
+ */
+ public static void sendHPDS(Client client)
+ throws IOException {
+ ByteBuffer rawBuf = allocBuffer(0);
+ JdwpPacket packet = new JdwpPacket(rawBuf);
+ ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+ finishChunkPacket(packet, CHUNK_HPDS, buf.position());
+ Log.d("ddm-heap", "Sending " + name(CHUNK_HPDS));
+ client.sendAndConsume(packet, mInst);
+ client.getClientData().setPendingHprofDump("[streaming]");
+ }
+
/*
* Handle notification of completion of a HeaP DUmp.
*/
@@ -274,6 +302,14 @@ final class HandleHeap extends ChunkHandler {
}
}
+ /*
+ * Handle HeaP Dump Streaming response. "data" contains the full
+ * hprof dump.
+ */
+ private void handleHPDS(Client client, ByteBuffer data) {
+ Log.w("ddm-prof", "got hprof file, size: " + data.capacity() + " bytes");
+ }
+
/**
* Sends a REAE (REcent Allocation Enable) request to the client.
*/