Merge "Implement dumpheap -m."
This commit is contained in:
committed by
Android (Google) Code Review
commit
f003ae0f25
@@ -658,6 +658,8 @@ public final class ActivityThread {
|
||||
}
|
||||
|
||||
static final class DumpHeapData {
|
||||
public boolean managed;
|
||||
public boolean mallocInfo;
|
||||
public boolean runGc;
|
||||
String path;
|
||||
ParcelFileDescriptor fd;
|
||||
@@ -1025,12 +1027,15 @@ public final class ActivityThread {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpHeap(boolean managed, boolean runGc, String path, ParcelFileDescriptor fd) {
|
||||
public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
|
||||
ParcelFileDescriptor fd) {
|
||||
DumpHeapData dhd = new DumpHeapData();
|
||||
dhd.managed = managed;
|
||||
dhd.mallocInfo = mallocInfo;
|
||||
dhd.runGc = runGc;
|
||||
dhd.path = path;
|
||||
dhd.fd = fd;
|
||||
sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/);
|
||||
sendMessage(H.DUMP_HEAP, dhd, 0, 0, true /*async*/);
|
||||
}
|
||||
|
||||
public void attachAgent(String agent) {
|
||||
@@ -1762,7 +1767,7 @@ public final class ActivityThread {
|
||||
case SCHEDULE_CRASH:
|
||||
throw new RemoteServiceException((String)msg.obj);
|
||||
case DUMP_HEAP:
|
||||
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
|
||||
handleDumpHeap((DumpHeapData) msg.obj);
|
||||
break;
|
||||
case DUMP_ACTIVITY:
|
||||
handleDumpActivity((DumpComponentInfo)msg.obj);
|
||||
@@ -5173,13 +5178,13 @@ public final class ActivityThread {
|
||||
}
|
||||
}
|
||||
|
||||
static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
|
||||
static void handleDumpHeap(DumpHeapData dhd) {
|
||||
if (dhd.runGc) {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
if (managed) {
|
||||
if (dhd.managed) {
|
||||
try {
|
||||
Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
|
||||
} catch (IOException e) {
|
||||
@@ -5192,6 +5197,8 @@ public final class ActivityThread {
|
||||
Slog.w(TAG, "Failure closing profile fd", e);
|
||||
}
|
||||
}
|
||||
} else if (dhd.mallocInfo) {
|
||||
Debug.dumpNativeMallocInfo(dhd.fd.getFileDescriptor());
|
||||
} else {
|
||||
Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
|
||||
}
|
||||
|
||||
@@ -277,8 +277,8 @@ interface IActivityManager {
|
||||
int checkGrantUriPermission(int callingUid, in String targetPkg, in Uri uri,
|
||||
int modeFlags, int userId);
|
||||
// Cause the specified process to dump the specified heap.
|
||||
boolean dumpHeap(in String process, int userId, boolean managed, boolean runGc, in String path,
|
||||
in ParcelFileDescriptor fd);
|
||||
boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
|
||||
boolean runGc, in String path, in ParcelFileDescriptor fd);
|
||||
int startActivities(in IApplicationThread caller, in String callingPackage,
|
||||
in Intent[] intents, in String[] resolvedTypes, in IBinder resultTo,
|
||||
in Bundle options, int userId);
|
||||
|
||||
@@ -117,7 +117,8 @@ oneway interface IApplicationThread {
|
||||
void scheduleSuicide();
|
||||
void dispatchPackageBroadcast(int cmd, in String[] packages);
|
||||
void scheduleCrash(in String msg);
|
||||
void dumpHeap(boolean managed, boolean runGc, in String path, in ParcelFileDescriptor fd);
|
||||
void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
|
||||
in ParcelFileDescriptor fd);
|
||||
void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
|
||||
in String[] args);
|
||||
void clearDnsCache();
|
||||
|
||||
@@ -1813,6 +1813,13 @@ public final class Debug
|
||||
*/
|
||||
public static native void dumpNativeHeap(FileDescriptor fd);
|
||||
|
||||
/**
|
||||
* Writes malloc info data to the specified file descriptor.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static native void dumpNativeMallocInfo(FileDescriptor fd);
|
||||
|
||||
/**
|
||||
* Returns a count of the extant instances of a class.
|
||||
*
|
||||
|
||||
@@ -48,10 +48,14 @@
|
||||
namespace android
|
||||
{
|
||||
|
||||
using UniqueFile = std::unique_ptr<FILE, decltype(&fclose)>;
|
||||
static void safeFclose(FILE* fp) {
|
||||
if (fp) fclose(fp);
|
||||
}
|
||||
|
||||
using UniqueFile = std::unique_ptr<FILE, decltype(&safeFclose)>;
|
||||
|
||||
static inline UniqueFile MakeUniqueFile(const char* path, const char* mode) {
|
||||
return UniqueFile(fopen(path, mode), fclose);
|
||||
return UniqueFile(fopen(path, mode), safeFclose);
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -972,21 +976,16 @@ static void dumpNativeHeap(FILE* fp)
|
||||
fprintf(fp, "END\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the native heap, writing human-readable output to the specified
|
||||
* file descriptor.
|
||||
*/
|
||||
static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
|
||||
jobject fileDescriptor)
|
||||
static bool openFile(JNIEnv* env, jobject fileDescriptor, UniqueFile& fp)
|
||||
{
|
||||
if (fileDescriptor == NULL) {
|
||||
jniThrowNullPointerException(env, "fd == null");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
|
||||
if (origFd < 0) {
|
||||
jniThrowRuntimeException(env, "Invalid file descriptor");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* dup() the descriptor so we don't close the original with fclose() */
|
||||
@@ -994,14 +993,28 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
|
||||
if (fd < 0) {
|
||||
ALOGW("dup(%d) failed: %s\n", origFd, strerror(errno));
|
||||
jniThrowRuntimeException(env, "dup() failed");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
UniqueFile fp(fdopen(fd, "w"), fclose);
|
||||
fp.reset(fdopen(fd, "w"));
|
||||
if (fp == nullptr) {
|
||||
ALOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
|
||||
close(fd);
|
||||
jniThrowRuntimeException(env, "fdopen() failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the native heap, writing human-readable output to the specified
|
||||
* file descriptor.
|
||||
*/
|
||||
static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject,
|
||||
jobject fileDescriptor)
|
||||
{
|
||||
UniqueFile fp(nullptr, safeFclose);
|
||||
if (!openFile(env, fileDescriptor, fp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1010,6 +1023,21 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
|
||||
ALOGD("Native heap dump complete.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the native malloc info, writing xml output to the specified
|
||||
* file descriptor.
|
||||
*/
|
||||
static void android_os_Debug_dumpNativeMallocInfo(JNIEnv* env, jobject,
|
||||
jobject fileDescriptor)
|
||||
{
|
||||
UniqueFile fp(nullptr, safeFclose);
|
||||
if (!openFile(env, fileDescriptor, fp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
malloc_info(0, fp.get());
|
||||
}
|
||||
|
||||
static bool dumpTraces(JNIEnv* env, jint pid, jstring fileName, jint timeoutSecs,
|
||||
DebuggerdDumpType dumpType) {
|
||||
const ScopedUtfChars fileNameChars(env, fileName);
|
||||
@@ -1070,6 +1098,8 @@ static const JNINativeMethod gMethods[] = {
|
||||
(void*) android_os_Debug_getMemInfo },
|
||||
{ "dumpNativeHeap", "(Ljava/io/FileDescriptor;)V",
|
||||
(void*) android_os_Debug_dumpNativeHeap },
|
||||
{ "dumpNativeMallocInfo", "(Ljava/io/FileDescriptor;)V",
|
||||
(void*) android_os_Debug_dumpNativeMallocInfo },
|
||||
{ "getBinderSentTransactions", "()I",
|
||||
(void*) android_os_Debug_getBinderSentTransactions },
|
||||
{ "getBinderReceivedTransactions", "()I",
|
||||
|
||||
@@ -21631,7 +21631,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
if (DEBUG_PSS) Slog.d(TAG_PSS,
|
||||
"Requesting dump heap from "
|
||||
+ myProc + " to " + heapdumpFile);
|
||||
thread.dumpHeap(/* managed=*/ true, /* runGc= */ false,
|
||||
thread.dumpHeap(/* managed= */ true,
|
||||
/* mallocInfo= */ false, /* runGc= */ false,
|
||||
heapdumpFile.toString(), fd);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
@@ -23394,8 +23395,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
return proc;
|
||||
}
|
||||
|
||||
public boolean dumpHeap(String process, int userId, boolean managed, boolean runGc,
|
||||
String path, ParcelFileDescriptor fd) throws RemoteException {
|
||||
public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
|
||||
boolean runGc, String path, ParcelFileDescriptor fd) throws RemoteException {
|
||||
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -23423,7 +23424,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
proc.thread.dumpHeap(managed, runGc, path, fd);
|
||||
proc.thread.dumpHeap(managed, mallocInfo, runGc, path, fd);
|
||||
fd = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -784,6 +784,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
int runDumpHeap(PrintWriter pw) throws RemoteException {
|
||||
final PrintWriter err = getErrPrintWriter();
|
||||
boolean managed = true;
|
||||
boolean mallocInfo = false;
|
||||
int userId = UserHandle.USER_CURRENT;
|
||||
boolean runGc = false;
|
||||
|
||||
@@ -799,6 +800,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
managed = false;
|
||||
} else if (opt.equals("-g")) {
|
||||
runGc = true;
|
||||
} else if (opt.equals("-m")) {
|
||||
managed = false;
|
||||
mallocInfo = true;
|
||||
} else {
|
||||
err.println("Error: Unknown option: " + opt);
|
||||
return -1;
|
||||
@@ -814,7 +818,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mInterface.dumpHeap(process, userId, managed, runGc, heapFile, fd)) {
|
||||
if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, heapFile, fd)) {
|
||||
err.println("HEAP DUMP FAILED on process " + process);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user