Skip to content

Instantly share code, notes, and snippets.

@ganadist
Last active August 29, 2015 14:14
Show Gist options
  • Select an option

  • Save ganadist/46afd6b4b39c826ee530 to your computer and use it in GitHub Desktop.

Select an option

Save ganadist/46afd6b4b39c826ee530 to your computer and use it in GitHub Desktop.
show BinderProxy reference information when run "dumpsys meminfo -a"
#!/usr/bin/env python2
import sys, os
import collections
def parse_meminfo(filename):
def parse(filename):
lines = []
for line in open(filename):
line = line[:-1]
if line.startswith('** MEMINFO in pid '):
if len(lines) > 3:
yield get_binder_info(lines)
lines = []
lines.append(line)
yield get_binder_info(lines)
d = {}
for pid, name, binder_info in parse(filename):
d[name] = binder_info
return d
def get_binder_info(item):
l = item[0].split()
pid = l[4]
pname = l[5][1:-1]
proxies = []
lines = []
for line in item[2:]:
if not line.strip():
proxies.append('\n'.join(lines))
lines = []
continue
if line.startswith(' Shared'):
break
lines.append(line)
return pid, pname, collections.Counter(proxies)
if __name__ == '__main__':
def parse_args(argv):
tags = []
filenames = []
for filename in argv:
if os.access(filename, os.R_OK):
filenames.append(filename)
else:
tags.append(filename)
return tags, filenames
tags, filenames = parse_args(sys.argv[1:])
if not filenames:
print 'Usage: %s dumpsys_meminfo_a_output1 dumpsys_meminfo_a_output2 ...'%sys.argv[0]
sys.exit(-1)
parsed = map(parse_meminfo, filenames)
now = parsed[-1]
if not tags:
tags = now.keys() # ['system', ]
for tag in tags:
printed = False
for k, v in now[tag].most_common(10):
if v < 4: continue
if not printed:
print 'process: ', tag
printed = True
print 'count history:', map(lambda x: x.get(tag, {}).get(k, 0), parsed)
print 'item: ', k
print
From d42e2221b30fb9a386cf531d37dc58ee91ba602e Mon Sep 17 00:00:00 2001
From: Young-Ho Cha <[email protected]>
Date: Wed, 07 May 2014 17:44:17 +0900
Subject: [PATCH] DO NOT MERGE: show BinderProxy reference information when run
"dumpsys meminfo -a"
Change-Id: I59b8816f9c5062d7bd233b3a635ff8e5c56d3927
Signed-off-by: Young-Ho Cha <[email protected]>
---
core/java/android/app/ActivityThread.java | 2 ++
core/java/android/os/Binder.java | 55 +++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9d821e1..3ecb69d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -935,6 +935,8 @@ public final class ActivityThread {
boolean dumpFullInfo, boolean dumpDalvik, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
+
+ Binder.dumpBinderProxyList(pw);
try {
dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik);
} finally {
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b4a4624..7830637 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -481,9 +481,15 @@ public class Binder implements IBinder {
return res;
}
+
+ /** @hide */
+ public static void dumpBinderProxyList(PrintWriter pw) {
+ BinderProxy.dumpBinderProxyList(pw);
+ }
}
final class BinderProxy implements IBinder {
+ private static final boolean FIND_POTENTIAL_LEAKS = true;
public native boolean pingBinder();
public native boolean isBinderAlive();
@@ -530,13 +536,62 @@ final class BinderProxy implements IBinder {
}
}
+ private static android.util.SparseArray<BinderProxyInfo> sBinderList =
+ new android.util.SparseArray();
+
+ static class BinderProxyInfo {
+ final int mPid;
+ final int mUid;
+ final StackTraceElement[] mSte;
+ BinderProxyInfo() {
+ mPid = Binder.getCallingPid();
+ mUid = Binder.getCallingUid();
+ StackTraceElement[] ste = Thread.currentThread().getStackTrace();
+ if (ste.length > 5) {
+ mSte = new StackTraceElement[ste.length - 5];
+ System.arraycopy(ste, 4, mSte, 0, ste.length - 5);
+ } else {
+ mSte = null;
+ }
+ }
+ }
+
+ public static void dumpBinderProxyList(PrintWriter pw) {
+ if (FIND_POTENTIAL_LEAKS) {
+ synchronized(sBinderList) {
+ pw.println("BinderProxy count = " + sBinderList.size());
+ for (int i = 0; i < sBinderList.size(); i++) {
+ BinderProxyInfo b = sBinderList.valueAt(i);
+ pw.println("BinderProxy instance is created by:");
+ pw.println("pid: " + b.mPid + " uid: " + b.mUid);
+ if (b.mSte != null) {
+ for (StackTraceElement ste: b.mSte) {
+ pw.println(ste.toString());
+ }
+ }
+ pw.println();
+ }
+ }
+ }
+ }
+
BinderProxy() {
+ if (FIND_POTENTIAL_LEAKS) {
+ synchronized(sBinderList) {
+ sBinderList.put(hashCode(), new BinderProxyInfo());
+ }
+ }
mSelf = new WeakReference(this);
}
@Override
protected void finalize() throws Throwable {
try {
+ if (FIND_POTENTIAL_LEAKS) {
+ synchronized(sBinderList) {
+ sBinderList.delete(hashCode());
+ }
+ }
destroy();
} finally {
super.finalize();
--
2.2.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment