leakcanary
leakcanary copied to clipboard
Total retain size is negative
Description
Use ObjectDominators().buildDominatorTree(graph, ignoredRefs)
analyze a hprof file to find large object in it. The total retain size is negative, and a lot of objects with a retain size morn than 2MB. This analyze cost all most 500s.
2024-08-10 11:30:45 [DEBUG] Total retained: -1636186211 bytes in 2027354 objects. Root dominators: 154364
2024-08-10 11:30:45 [DEBUG] class android.content.Intent #37425 Retained: 647898632 bytes (2992 self) 246 objects
├─java.lang.String #1584699 Retained: 2644472 bytes
2024-08-10 11:30:45 [DEBUG] class java.lang.Character$UnicodeBlock #38890 Retained: 552699958 bytes (1950 self) 421 objects
├─java.lang.Character$UnicodeBlock #1687945 Retained: 2644484 bytes (12 self) 2 objects
| ╰─java.lang.String #1567201 Retained: 2644472 bytes
2024-08-10 11:30:45 [DEBUG] java.security.Provider$Service #1723297 Retained: 60826466 bytes (52 self) 49 objects
├─java.util.ArrayList #1723299 Retained: 55537470 bytes (20 self) 46 objects
| ╰─java.lang.Object[] #2438100 Retained: 55537450 bytes (240 self) 45 objects
| ├─java.lang.String #1725818 Retained: 2644472 bytes
Steps to Reproduce
- dump a hprof file from android device
- buildDominatorTree like below
heapDumpFile.openHeapGraph(proguardMapping = proguardMapping).use { graph ->
val weakAndFinalizerRefs = EnumSet.of(REFERENCES, FINALIZER_WATCHDOG_DAEMON)
val ignoredRefs = ReferenceMatcher.fromListBuilders(weakAndFinalizerRefs).map { matcher ->
matcher as IgnoredReferenceMatcher
}
val dominatorTree = ObjectDominators().buildDominatorTree(graph, ignoredRefs)
val root = dominatorTree.getValue(ValueHolder.NULL_REFERENCE)
val summary =
"Total retained: ${root.retainedSize} bytes in ${root.retainedCount} objects. Root dominators: ${root.dominatedObjectIds.size}\n\n"
...
- Look at the log output
Version Information
- LeakCanary version: 3.0-alpha-8
- Android OS version: 5.1
- Gradle version:8.5