Merge pull request #2679 from square/py/fix_android_growth_crash
Fix warmup for Android heap growth
diff --git a/leakcanary/leakcanary-android-test/build.gradle b/leakcanary/leakcanary-android-test/build.gradle
index 84424b4..dac237e 100644
--- a/leakcanary/leakcanary-android-test/build.gradle
+++ b/leakcanary/leakcanary-android-test/build.gradle
@@ -8,6 +8,11 @@
api projects.leakcanary.leakcanaryCore
api projects.leakcanary.leakcanaryAndroidUtils
api projects.shark.sharkAndroid
+
+ androidTestImplementation libs.androidX.multidex
+ androidTestImplementation libs.androidX.test.core
+ androidTestImplementation libs.androidX.test.runner
+ androidTestImplementation libs.assertjCore
}
android {
@@ -15,7 +20,10 @@
defaultConfig {
targetSdk versions.compileSdk
minSdk versions.minSdk
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildFeatures.buildConfig = false
- namespace 'com.squareup.leakcanary.core'
+ namespace 'com.squareup.leakcanary.android.test'
+ testNamespace 'com.squareup.leakcanary.android.test.test'
}
diff --git a/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml b/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..d56e207
--- /dev/null
+++ b/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <application
+ android:name="androidx.multidex.MultiDexApplication"
+ >
+ </application>
+</manifest>
diff --git a/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt b/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt
new file mode 100644
index 0000000..d2d6bde
--- /dev/null
+++ b/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt
@@ -0,0 +1,38 @@
+package leakcanary
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+import shark.ObjectGrowthDetector
+import shark.RepeatingScenarioObjectGrowthDetector.Companion.DEFAULT_MAX_HEAP_DUMPS
+import shark.RepeatingScenarioObjectGrowthDetector.Companion.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP
+import shark.forAndroidHeap
+
+class RepeatingAndroidInProcessScenarioTest {
+
+ private val growingList = mutableListOf<String>()
+
+ @Test fun failing_scenario_iterates_to_max_heap_dumps_times_loops_per_dump() {
+ val detector = ObjectGrowthDetector.forAndroidHeap()
+ .repeatingAndroidInProcessScenario()
+ var iteration = 0
+ detector.findRepeatedlyGrowingObjects {
+ growingList += "growth $iteration"
+ iteration++
+ }
+
+ assertThat(iteration).isEqualTo(DEFAULT_MAX_HEAP_DUMPS * IN_PROCESS_SCENARIO_LOOPS_PER_DUMP)
+ }
+
+ @Test fun failing_scenario_finds_expected_growing_object() {
+ val detector = ObjectGrowthDetector.forAndroidHeap()
+ .repeatingAndroidInProcessScenario()
+ var iteration = 0
+ val heapGrowth = detector.findRepeatedlyGrowingObjects {
+ growingList += "growth $iteration"
+ iteration++
+ }
+
+ val growingObject = heapGrowth.growingObjects.single()
+ assertThat(growingObject.name).startsWith("INSTANCE_FIELD RepeatingAndroidInProcessScenarioTest.growingList")
+ }
+}
diff --git a/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt b/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
index fc65e2d..1dddeb2 100644
--- a/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
+++ b/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
@@ -17,14 +17,13 @@
*/
fun ObjectGrowthDetector.repeatingAndroidInProcessScenario(
maxHeapDumps: Int = RepeatingScenarioObjectGrowthDetector.DEFAULT_MAX_HEAP_DUMPS,
- // In process => More than one to account for the impact of running the analysis.
- scenarioLoopsPerDump: Int = 2,
+ scenarioLoopsPerDump: Int = RepeatingScenarioObjectGrowthDetector.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP,
): RepeatingScenarioObjectGrowthDetector {
return repeatingScenario(
heapGraphProvider = HeapGraphProvider.dumpingAndDeleting(
heapDumper = HeapDumper.forAndroidInProcess()
.withGc(gcTrigger = GcTrigger.inProcess())
- .withDetectorWarmup(this),
+ .withDetectorWarmup(this, androidHeap = true),
heapDumpFileProvider = HeapDumpFileProvider.tempFile()
),
maxHeapDumps = maxHeapDumps,
diff --git a/leakcanary/leakcanary-core/api/leakcanary-core.api b/leakcanary/leakcanary-core/api/leakcanary-core.api
index af0bddc..f9db10d 100644
--- a/leakcanary/leakcanary-core/api/leakcanary-core.api
+++ b/leakcanary/leakcanary-core/api/leakcanary-core.api
@@ -51,7 +51,7 @@
public final class leakcanary/ObjectGrowthWarmupHeapDumper : leakcanary/HeapDumper {
public static final field Companion Lleakcanary/ObjectGrowthWarmupHeapDumper$Companion;
- public fun <init> (Lshark/ObjectGrowthDetector;Lleakcanary/HeapDumper;)V
+ public fun <init> (Lshark/ObjectGrowthDetector;Lleakcanary/HeapDumper;Z)V
public fun dumpHeap (Ljava/io/File;)V
}
@@ -59,7 +59,7 @@
}
public final class leakcanary/ObjectGrowthWarmupHeapDumperKt {
- public static final fun withDetectorWarmup (Lleakcanary/HeapDumper;Lshark/ObjectGrowthDetector;)Lleakcanary/HeapDumper;
+ public static final fun withDetectorWarmup (Lleakcanary/HeapDumper;Lshark/ObjectGrowthDetector;Z)Lleakcanary/HeapDumper;
}
public final class leakcanary/TempHeapDumpFileProvider : leakcanary/HeapDumpFileProvider {
diff --git a/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt b/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
index ee184cb..2890991 100644
--- a/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
+++ b/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
@@ -9,7 +9,8 @@
class ObjectGrowthWarmupHeapDumper(
private val objectGrowthDetector: ObjectGrowthDetector,
- private val delegate: HeapDumper
+ private val delegate: HeapDumper,
+ private val androidHeap: Boolean
) : HeapDumper {
private var warm = false
@@ -23,7 +24,8 @@
}
private fun warmup() {
- val heapDumpsAsHex = listOf({ heapDump1Hex() }, { heapDump2Hex() }, { heapDump3Hex() })
+ val heapDumpsAsHex = listOf({ heapDump1Hex(androidHeap) }, { heapDump2Hex(androidHeap) },
+ { heapDump3Hex(androidHeap) })
val heapDumpsAsHexIterator = heapDumpsAsHex.iterator()
val warmupDetector = objectGrowthDetector.repeatingScenario(
heapGraphProvider = {
@@ -44,16 +46,28 @@
// then 00 is the string separator
// 00000004 is the identifier byte size, 4 bytes
// 0b501e7e ca55e77e (obsolete cassette) is a cool heap dump timestamp.
- internal fun heapDump1Hex() =
+ internal fun heapDump1Hex(androidHeap: Boolean) = if (androidHeap) {
+ "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000004a200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e0000000100000005000000002c00000000000000000100000000000000160000001f6a6176612e6c616e672e4f626a6563745b5d0200000000000000100000000100000020000000010000001f0c000000000000004520000000200000000100000005000000000000000000000000000000000000000000000000000000000000050000002022000000210000000100000001000000200000001e2c000000000000000001000000000000000a00000022486f6c64657202000000000000001000000001000000230000000100000022010000000000000008000000246c6973740c00000000000000392000000023000000010000000500000000000000000000000000000000000000000000000000000001000000240200000021000005000000232c0000000000000000"
+ } else {
"4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000622000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f0000000100000005000000002c0000000000000000010000000000000016000000106a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001100000001000000100c000000000000004520000000110000000100000005000000000000000000000000000000000000000000000000000000000000050000001122000000120000000100000001000000110000000f2c000000000000000001000000000000000a00000013486f6c64657202000000000000001000000001000000140000000100000013010000000000000008000000156c6973740c00000000000000392000000014000000010000000500000000000000000000000000000000000000000000000000000001000000150200000012000005000000142c0000000000000000"
+ }
- internal fun heapDump2Hex() =
+ internal fun heapDump2Hex(androidHeap: Boolean) = if (androidHeap) {
+ "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000005b200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e000000010000000500000000210000001f0000000100000005000000002c0000000000000000010000000000000016000000206a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000002100000001000000200c000000000000004920000000210000000100000005000000000000000000000000000000000000000000000000000000000000050000002122000000220000000100000002000000210000001e0000001f2c000000000000000001000000000000000a00000023486f6c64657202000000000000001000000001000000240000000100000023010000000000000008000000256c6973740c00000000000000392000000024000000010000000500000000000000000000000000000000000000000000000000000001000000250200000022000005000000242c0000000000000000"
+ } else {
"4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000732000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f00000001000000050000000021000000100000000100000005000000002c0000000000000000010000000000000016000000116a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001200000001000000110c000000000000004920000000120000000100000005000000000000000000000000000000000000000000000000000000000000050000001222000000130000000100000002000000120000000f000000102c000000000000000001000000000000000a00000014486f6c64657202000000000000001000000001000000150000000100000014010000000000000008000000166c6973740c00000000000000392000000015000000010000000500000000000000000000000000000000000000000000000000000001000000160200000013000005000000152c0000000000000000"
+ }
- internal fun heapDump3Hex() =
+ internal fun heapDump3Hex(androidHeap: Boolean) = if (androidHeap) {
+ "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000006c200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e000000010000000500000000210000001f00000001000000050000000021000000200000000100000005000000002c0000000000000000010000000000000016000000216a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000002200000001000000210c000000000000004d20000000220000000100000005000000000000000000000000000000000000000000000000000000000000050000002222000000230000000100000003000000220000001e0000001f000000202c000000000000000001000000000000000a00000024486f6c64657202000000000000001000000001000000250000000100000024010000000000000008000000266c6973740c00000000000000392000000025000000010000000500000000000000000000000000000000000000000000000000000001000000260200000023000005000000252c0000000000000000"
+ } else {
"4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000842000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f000000010000000500000000210000001000000001000000050000000021000000110000000100000005000000002c0000000000000000010000000000000016000000126a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001300000001000000120c000000000000004d20000000130000000100000005000000000000000000000000000000000000000000000000000000000000050000001322000000140000000100000003000000130000000f00000010000000112c000000000000000001000000000000000a00000015486f6c64657202000000000000001000000001000000160000000100000015010000000000000008000000176c6973740c00000000000000392000000016000000010000000500000000000000000000000000000000000000000000000000000001000000170200000014000005000000162c0000000000000000"
+ }
}
}
-fun HeapDumper.withDetectorWarmup(objectGrowthDetector: ObjectGrowthDetector): HeapDumper =
- ObjectGrowthWarmupHeapDumper(objectGrowthDetector, this)
+fun HeapDumper.withDetectorWarmup(
+ objectGrowthDetector: ObjectGrowthDetector,
+ androidHeap: Boolean
+): HeapDumper =
+ ObjectGrowthWarmupHeapDumper(objectGrowthDetector, this, androidHeap)
diff --git a/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt b/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
index 002d0da..271a739 100644
--- a/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
+++ b/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
@@ -5,34 +5,68 @@
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import shark.HprofHeader
+import shark.HprofWriterHelper
+import shark.ValueHolder
import shark.dumpToBytes
class ObjectGrowthWarmupHeapDumperTest {
@Test fun `heap dump 1 as hex constant matches generated heap dump hex`() {
- assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex()).isEqualTo(dumpGrowingListHeapAsHex(1))
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(1))
}
@Test fun `heap dump 2 as hex constant matches generated heap dump hex`() {
- assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex()).isEqualTo(dumpGrowingListHeapAsHex(2))
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(2))
}
@Test fun `heap dump 3 as hex constant matches generated heap dump hex`() {
- assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex()).isEqualTo(dumpGrowingListHeapAsHex(3))
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(3))
+ }
+
+ @Test fun `android heap dump 1 as hex constant matches generated heap dump hex`() {
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(1))
+ }
+
+ @Test fun `android heap dump 2 as hex constant matches generated heap dump hex`() {
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(2))
+ }
+
+ @Test fun `android heap dump 3 as hex constant matches generated heap dump hex`() {
+ assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(3))
}
private fun dumpGrowingListHeapAsHex(listItemCount: Int): String {
val heapDumpTimestamp = ("0b501e7e" + "ca55e77e").decodeHex().toByteArray().toLong()
return dumpToBytes(hprofHeader = HprofHeader(heapDumpTimestamp = heapDumpTimestamp)) {
- "Holder" clazz {
- val refs = (1..listItemCount).map {
- instance(objectClassId)
- }.toTypedArray()
- staticField["list"] = objectArray(*refs)
- }
+ growingList(listItemCount)
}.toByteString().hex()
}
+ private fun dumpAndroidGrowingListHeapAsHex(listItemCount: Int): String {
+ val heapDumpTimestamp = ("0b501e7e" + "ca55e77e").decodeHex().toByteArray().toLong()
+ return dumpToBytes(hprofHeader = HprofHeader(heapDumpTimestamp = heapDumpTimestamp)) {
+ "android.os.Build" clazz {
+ staticField["MANUFACTURER"] = string("M")
+ staticField["ID"] = string("I")
+ }
+ "android.os.Build\$VERSION" clazz {
+ staticField["SDK_INT"] = ValueHolder.IntHolder(42)
+ }
+ growingList(listItemCount)
+ }.toByteString().hex()
+ }
+
+
+ private fun HprofWriterHelper.growingList(listItemCount: Int) {
+ "Holder" clazz {
+ val refs = (1..listItemCount).map {
+ instance(objectClassId)
+ }.toTypedArray()
+ staticField["list"] = objectArray(*refs)
+ }
+ }
+
+
private fun ByteArray.toLong(): Long {
check(size == 8)
var pos = 0
diff --git a/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt b/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
index 9dede19..a476123 100644
--- a/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
+++ b/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
@@ -17,14 +17,13 @@
*/
fun ObjectGrowthDetector.repeatingJvmInProcessScenario(
maxHeapDumps: Int = RepeatingScenarioObjectGrowthDetector.DEFAULT_MAX_HEAP_DUMPS,
- // In process => More than one to account for the impact of running the analysis.
- scenarioLoopsPerDump: Int = 2,
+ scenarioLoopsPerDump: Int = RepeatingScenarioObjectGrowthDetector.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP,
): RepeatingScenarioObjectGrowthDetector {
return repeatingScenario(
heapGraphProvider = HeapGraphProvider.dumpingAndDeleting(
heapDumper = HeapDumper.forJvmInProcess()
.withGc(gcTrigger = GcTrigger.inProcess())
- .withDetectorWarmup(this),
+ .withDetectorWarmup(this, androidHeap = false),
heapDumpFileProvider = HeapDumpFileProvider.tempFile()
),
maxHeapDumps = maxHeapDumps,
diff --git a/shark/shark/api/shark.api b/shark/shark/api/shark.api
index c6577c1..1224855 100644
--- a/shark/shark/api/shark.api
+++ b/shark/shark/api/shark.api
@@ -940,6 +940,7 @@
public static final field Companion Lshark/RepeatingScenarioObjectGrowthDetector$Companion;
public static final field DEFAULT_MAX_HEAP_DUMPS I
public static final field DEFAULT_SCENARIO_LOOPS_PER_DUMP I
+ public static final field IN_PROCESS_SCENARIO_LOOPS_PER_DUMP I
public fun <init> (Lshark/HeapGraphProvider;Lshark/ObjectGrowthDetector;II)V
public synthetic fun <init> (Lshark/HeapGraphProvider;Lshark/ObjectGrowthDetector;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun findRepeatedlyGrowingObjects (Lkotlin/jvm/functions/Function0;)Lshark/HeapGrowthTraversal;
diff --git a/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt b/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
index d98e735..52dcd48 100644
--- a/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
+++ b/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
@@ -48,6 +48,11 @@
companion object {
const val DEFAULT_MAX_HEAP_DUMPS = 5
const val DEFAULT_SCENARIO_LOOPS_PER_DUMP = 1
+
+ /**
+ * In process => More than one to account for the impact of running the analysis.
+ */
+ const val IN_PROCESS_SCENARIO_LOOPS_PER_DUMP = 2
}
}