Loading core/java/android/os/Binder.java +53 −5 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Base class for a remotable object, the core part of a lightweight Loading Loading @@ -888,17 +891,62 @@ final class BinderProxy implements IBinder { keyArray[size] = key; } if (size >= mWarnBucketSize) { final int total_size = size(); final int totalSize = size(); Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size + " total = " + total_size); + " total = " + totalSize); mWarnBucketSize += WARN_INCREMENT; if (Build.IS_DEBUGGABLE && total_size > CRASH_AT_SIZE) { throw new AssertionError("Binder ProxyMap has too many entries. " + "BinderProxy leak?"); if (Build.IS_DEBUGGABLE && totalSize > CRASH_AT_SIZE) { diagnosticCrash(); } } } /** * Dump a histogram to the logcat, then throw an assertion error. Used to diagnose * abnormally large proxy maps. */ private void diagnosticCrash() { Map<String, Integer> counts = new HashMap<>(); for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) { if (a != null) { for (WeakReference<BinderProxy> weakRef : a) { BinderProxy bp = weakRef.get(); String key; if (bp == null) { key = "<cleared weak-ref>"; } else { try { key = bp.getInterfaceDescriptor(); } catch (Throwable t) { key = "<exception during getDescriptor>"; } } Integer i = counts.get(key); if (i == null) { counts.put(key, 1); } else { counts.put(key, i + 1); } } } } Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray( new Map.Entry[counts.size()]); Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) -> b.getValue().compareTo(a.getValue())); Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):"); int printLength = Math.min(10, sorted.length); for (int i = 0; i < printLength; i++) { Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x" + sorted[i].getValue()); } // Now throw an assertion. final int totalSize = size(); throw new AssertionError("Binder ProxyMap has too many entries: " + totalSize + ". BinderProxy leak?"); } // Corresponding ArrayLists in the following two arrays always have the same size. // They contain no empty entries. However WeakReferences in the values ArrayLists // may have been cleared. Loading Loading
core/java/android/os/Binder.java +53 −5 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Base class for a remotable object, the core part of a lightweight Loading Loading @@ -888,17 +891,62 @@ final class BinderProxy implements IBinder { keyArray[size] = key; } if (size >= mWarnBucketSize) { final int total_size = size(); final int totalSize = size(); Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size + " total = " + total_size); + " total = " + totalSize); mWarnBucketSize += WARN_INCREMENT; if (Build.IS_DEBUGGABLE && total_size > CRASH_AT_SIZE) { throw new AssertionError("Binder ProxyMap has too many entries. " + "BinderProxy leak?"); if (Build.IS_DEBUGGABLE && totalSize > CRASH_AT_SIZE) { diagnosticCrash(); } } } /** * Dump a histogram to the logcat, then throw an assertion error. Used to diagnose * abnormally large proxy maps. */ private void diagnosticCrash() { Map<String, Integer> counts = new HashMap<>(); for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) { if (a != null) { for (WeakReference<BinderProxy> weakRef : a) { BinderProxy bp = weakRef.get(); String key; if (bp == null) { key = "<cleared weak-ref>"; } else { try { key = bp.getInterfaceDescriptor(); } catch (Throwable t) { key = "<exception during getDescriptor>"; } } Integer i = counts.get(key); if (i == null) { counts.put(key, 1); } else { counts.put(key, i + 1); } } } } Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray( new Map.Entry[counts.size()]); Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) -> b.getValue().compareTo(a.getValue())); Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):"); int printLength = Math.min(10, sorted.length); for (int i = 0; i < printLength; i++) { Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x" + sorted[i].getValue()); } // Now throw an assertion. final int totalSize = size(); throw new AssertionError("Binder ProxyMap has too many entries: " + totalSize + ". BinderProxy leak?"); } // Corresponding ArrayLists in the following two arrays always have the same size. // They contain no empty entries. However WeakReferences in the values ArrayLists // may have been cleared. Loading