Skip to content

Commit d468fcb

Browse files
authored
Update changelogs and docs for release (#1505)
1 parent 4ce2872 commit d468fcb

File tree

9 files changed

+147
-35
lines changed

9 files changed

+147
-35
lines changed

docs/changelog.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,31 @@
11
# Change Log
22

3-
## Version 2.0 Alpha 3 (2019-07-04)
3+
## Version 2.0 Beta 1 (2019-17-30)
4+
5+
LeakCanary 2 reached **beta status**: the internals and APIs are mostly stable.
6+
7+
Now is a great time to adopt it and provide feedback before the stable release. We're counting on you to find bugs and suggest improvements! Check out the new [Getting Started](https://square.github.io/leakcanary/getting_started) instructions and the [migration guide](https://square.github.io/leakcanary/upgrading-to-leakcanary-2.0/).
8+
9+
* New standalone library! [Shark](shark.md) is the heap analyzer that powers LeakCanary 2, and it can run in any Java VM. It comes with a [CLI](shark.md#shark-cli): you can now run `shark-cli analyze-process com.example.myapp` from your computer.
10+
* New Heap Explorer directly on device! Open a Heap Analysis in LeakCanary, tap the options menu and select "Heap Explorer". This is still experimental and not very user friendly, contributions welcome!
11+
* **Large API rewrite** to improve usability. If you used the alpha with a customized configuration, there are breaking changes. Of note: LeakSentry became [AppWatcher](/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/), RefWatcher became [ObjectWatcher](/api/leakcanary-object-watcher/leakcanary/-object-watcher/), AndroidExcludedRefs became [AndroidReferenceMatchers](/api/shark-android/shark/-android-reference-matchers/), AnalysisResultListener became [OnHeapAnalyzedListener](/api/leakcanary-android-core/leakcanary/-on-heap-analyzed-listener/), AndroidLeakTraceInspectors became [AndroidObjectInspectors](/api/shark-android/shark/-android-object-inspectors/).
12+
* The entire API surface is now documented and the documentation is available on this website: try the search bar at the top and **LeakCanary API ∨** in the navigation menu.
13+
* Removed the **dependency on Android X**. No more configuration issues! [#1462](https://github.com/square/leakcanary/issues/1462)
14+
* Added **Proguard rules** for LeakCanary and ObjectWatcher. [#1500](https://github.com/square/leakcanary/pull/1500)
15+
* Display LeakCanary version in the About screen. [#1448](https://github.com/square/leakcanary/issues/1448)
16+
* Bug fixes, new reference matchers and object inspectors
17+
18+
Many thanks to
19+
[@arctouch-carlosottoboni](https://github.com/arctouch-carlosottoboni),
20+
[@jemaystermind](https://github.com/jemaystermind),
21+
[@kushagrakumar27](https://github.com/kushagrakumar27),
22+
[@pyricau](https://github.com/pyricau),
23+
[@snkashis](https://github.com/snkashis)
24+
for the contributions, bug reports and feature requests.
425

5-
**Thanks for testing the alpha**, we're counting on you to help us find bugs and suggest improvements! Check out the new [Getting Started](https://square.github.io/leakcanary/getting_started) instructions and the [migration guide](https://square.github.io/leakcanary/upgrading-to-leakcanary-2.0/).
26+
For more details, see the [2.0-beta-1 Milestone](https://github.com/square/leakcanary/milestone/1) and the [full diff](https://github.com/square/leakcanary/compare/v2.0-alpha-3...v2.0-beta-1).
27+
28+
## Version 2.0 Alpha 3 (2019-07-04)
629

730
* [#1401](https://github.com/square/leakcanary/pull/1401) LeakCanary can now import all hprof files created from prior LeakCanary versions.
831
* [#1414](https://github.com/square/leakcanary/pull/1414) New API: `RefWatcher.retainedInstances` which returns the instances that are currently considered retained.

docs/faq.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
## Can a leak be caused by the Android SDK?
44

5-
Yes. There are a number of known memory leaks that have been fixed over time in AOSP as well as in manufacturer implementations. When such a leak occurs, there is little you can do as an app developer to fix it. For that reason, LeakCanary has a built-in list of known Android leaks to ignore: [AndroidExcludedRefs.kt](https://github.com/square/leakcanary/blob/master/leakcanary-analyzer/src/main/java/leakcanary/AndroidExcludedRefs.kt).
5+
Yes. There are a number of known memory leaks that have been fixed over time in AOSP as well as in manufacturer implementations. When such a leak occurs, there is little you can do as an app developer to fix it. For that reason, LeakCanary has a built-in list of known Android leaks to ignore: [AndroidReferenceMatchers](/api/shark-android/shark/-android-reference-matchers/).
66

77
If you find a new one, please [create an issue](https://github.com/square/leakcanary/issues/new/choose) and follow these steps:
88

99
1. Provide the entire leak trace information (reference key, device, etc), and use backticks (`) for formatting.
10-
2. Read the AOSP source for that version of Android, and try to figure out why it happens. You can easily navigate through SDK versions [android/platform_frameworks_base](https://github.com/android/platform_frameworks_base).
10+
2. Read the AOSP source for that version of Android, and try to figure out why it happens. You can easily navigate through SDK versions by switching branches on the GitHub mirror: [android/platform_frameworks_base](https://github.com/android/platform_frameworks_base).
1111
3. Check if it happens on the latest version of Android, and otherwise use blame to find when it was fixed.
1212
4. If it's still happening, build a simple repro case.
1313
5. File an issue on [b.android.com](http://b.android.com) with the leak trace and the repro case.
@@ -46,7 +46,7 @@ Update your dependencies to the latest SNAPSHOT (see [build.gradle](https://gith
4646

4747
```gradle
4848
dependencies {
49-
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-alpha-4-SNAPSHOT'
49+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-2-SNAPSHOT'
5050
}
5151
```
5252

docs/fundamentals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ The chain of references from the GC root to the leaking instance is what is prev
143143
│ View.mWindowAttachCount=1
144144
```
145145

146-
LeakCanary runs heuristics to determine the lifecycle state of the nodes of the leak trace, and therefore whether they are leaking or not. For example, if a view has `View#mAttachInfo = null` and `mParent != null` then it is detached yet has a parent, so that view is probably leaking. In the leak trace, for each node you'll see `Leaking: YES / NO / UNKNOWN` with an explanation in parenthesis. LeakCanary can also surface extra information about the state of a node, e.g. `View.mWindowAttachCount=1`. LeakCanary comes with a set of default heuristics ([AndroidObjectInspectors](/api/shark-android/shark/-android-object-inspectors/), you can add your own heuristics by updating [LeakCanary.Config.objectInspectors](/api/leakcanary-android-core/leakcanary/-leak-canary/-config/object-inspectors/).
146+
LeakCanary runs heuristics to determine the lifecycle state of the nodes of the leak trace, and therefore whether they are leaking or not. For example, if a view has `View#mAttachInfo = null` and `mParent != null` then it is detached yet has a parent, so that view is probably leaking. In the leak trace, for each node you'll see `Leaking: YES / NO / UNKNOWN` with an explanation in parenthesis. LeakCanary can also surface extra information about the state of a node, e.g. `View.mWindowAttachCount=1`. LeakCanary comes with a set of default heuristics: [AndroidObjectInspectors](/api/shark-android/shark/-android-object-inspectors/). You can add your own heuristics by updating [LeakCanary.Config.objectInspectors](/api/leakcanary-android-core/leakcanary/-leak-canary/-config/object-inspectors/) (see the [recipe](recipes.md#identifying-leaking-objects-and-labeling-objects)).
147147

148148
### Narrowing down the cause of a leak
149149

docs/getting_started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ dependencies {
99
}
1010
```
1111

12-
**That's it, there is no code change needed!** [Here's why](faq.md#how-does-leakcanary-get-installed-by-only-adding-a-dependency). LeakCanary will automatically show a notification when a memory leak is detected in debug builds.
12+
**That's it, there is no code change needed!** LeakCanary will automatically show a notification when a memory leak is detected in debug builds.
1313

1414
What's next?
1515

1616
* Learn the [Fundamentals](fundamentals.md)
1717
* Try the [code recipes](recipes.md)
18-
* Read the [FAQ](faq.md)
18+
* Read the [FAQ](faq.md), e.g. [How does LeakCanary get installed by only adding a dependency?](faq.md#how-does-leakcanary-get-installed-by-only-adding-a-dependency)

docs/recipes.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ If you think a recipe might be missing or you're not sure that what you're tryin
44

55
## Configuring AppWatcher in `object-watcher-android`
66

7-
AppWatcher is in charge of detecting retained objects. Its configuration can be updated at any time by replacing `AppWatcher.config`:
7+
AppWatcher is in charge of detecting retained objects. Its configuration can be updated at any time by replacing [AppWatcher.config](/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/config/):
88
```kotlin
99
class DebugExampleApplication : ExampleApplication() {
1010

@@ -17,7 +17,7 @@ class DebugExampleApplication : ExampleApplication() {
1717

1818
## Configuring LeakCanary
1919

20-
LeakCanary can be configured by replacing `LeakCanary.config`:
20+
LeakCanary can be configured by replacing [LeakCanary.config](/api/leakcanary-android-core/leakcanary/-leak-canary/config/):
2121

2222
```kotlin
2323
disableLeakCanaryButton.setOnClickListener {
@@ -27,7 +27,7 @@ disableLeakCanaryButton.setOnClickListener {
2727

2828
## Watching objects with a lifecycle
2929

30-
In your application, you may have other objects with a lifecycle, such as fragments, services, Dagger components, etc. Use `AppWatcher.objectWatcher` to watch instances that should be garbage collected:
30+
In your application, you may have other objects with a lifecycle, such as fragments, services, Dagger components, etc. Use [AppWatcher.objectWatcher](/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/object-watcher/) to watch instances that should be garbage collected:
3131

3232
```kotlin
3333
class MyService : Service {
@@ -118,7 +118,7 @@ res/
118118

119119
You can change the default behavior to upload the analysis result to a server of your choosing.
120120

121-
Create a custom `AnalysisResultListener` that delegates to the default:
121+
Create a custom [OnHeapAnalyzedListener](/api/leakcanary-android-core/leakcanary/-on-heap-analyzed-listener/) that delegates to [DefaultOnHeapAnalyzedListener](/api/leakcanary-android-core/leakcanary/-default-on-heap-analyzed-listener/):
122122

123123
```kotlin
124124
class LeakUploader : OnHeapAnalyzedListener {
@@ -134,7 +134,7 @@ class LeakUploader : OnHeapAnalyzedListener {
134134
}
135135
```
136136

137-
Set `analysisResultListener` on the LeakCanary config:
137+
Set [LeakCanary.config.onHeapAnalyzedListener](/api/leakcanary-android-core/leakcanary/-leak-canary/-config/on-heap-analyzed-listener/):
138138

139139
```kotlin
140140
class DebugExampleApplication : ExampleApplication() {

docs/shark.md

Lines changed: 87 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,75 @@
77
<img src="https://github.com/square/leakcanary/wiki/assets/shark.png" />
88
</p>
99

10-
Shark is the heap analyzer that powers LeakCanary. It's a standalone heap analyzer Kotlin library that can run in Java and Android VMs at **high speed** with a **low memory footprint**. It can analyze both Android and Java VM hprof files.
10+
Shark is the heap analyzer that powers LeakCanary 2. It's a Kotlin standalone heap analysis library that runs at **high speed** with a **low memory footprint**.
1111

12-
Shark is released as several distinct libraries:
12+
Shark is released in layers:
1313

14-
* `Shark Hprof`: Read and write records in hprof files
15-
* `Shark Graph`: Navigate the heap object graph
16-
* `Shark`: Generate heap analysis reports
17-
* `Shark Android`: Generate Android tailored heap analysis reports
14+
1. **Shark Hprof**: Read and write records in hprof files.
15+
2. **Shark Graph**: Navigate the heap object graph.
16+
3. **Shark**: Generate heap analysis reports.
17+
4. **Shark Android**: Android heuristics to generate tailored heap analysis reports.
18+
5. **Shark CLI**: Analyze the heap of debuggable apps installed on an Android device connected to your desktop. The output is similar to the output of LeakCanary, except you don't have to add the LeakCanary dependency to your app.
19+
6. **LeakCanary**: Builds on top. It automatically watches destroyed activities and fragments, triggers a heap dump, runs Shark Android and then displays the result.
1820

19-
Shark is also released as a CLI tool, `Shark CLI`.
21+
A few more things:
2022

21-
## Example usage
23+
* Shark is built on top of Okio. Okio makes it easy to parse heap dumps efficiently.
24+
* Shark is a 100% Kotlin library, and Kotlin is essential to its design, because Shark relies heavily on sealed classes and sequences to save memory.
25+
* Shark has the unique ability to help narrow down the cause of memory leaks through platform specific [heuristics](fundamentals.md#heuristics-and-labels).
26+
* Shark is heavily tested (80% test coverage).
27+
* Shark can run in both Java and Android VMs, with no other dependency than Okio and Kotlin.
28+
* Shark can analyze both Java and Android VM hprof files.
2229

23-
### Reading records in a hprof file with shark-hprof
30+
## Shark CLI
31+
32+
The Shark Command Line Interface (CLI) enables you to analyze heaps directly from your computer. It can dump the heap of an app installed on a connected Android device, analyze it, and even strip a heap dump of any sensitive data (e.g. PII, passwords or encryption keys) which is useful when sharing a heap dump.
33+
34+
Download it [here](https://github.com/square/leakcanary/releases/download/v2.0-beta-1/shark-cli-2.0-beta-1.zip)!
35+
36+
Usage instructions:
37+
38+
```
39+
$ ./bin/shark-cli
40+
41+
Shark CLI
42+
43+
^`. .=""=.
44+
^_ \ \ / _ _ \
45+
\ \ { \ | d b |
46+
{ \ / `~~~--__ \ /\ /
47+
{ \___----~~' `~~-_/'-=\/=-'\,
48+
\ /// a `~. \ \
49+
/ /~~~~-, ,__. , /// __,,,,) \ |
50+
\/ \/ `~~~; ,---~~-_`/ \ / \/
51+
/ / '. .'
52+
'._.' _|`~~`|_
53+
/|\ /|\
54+
55+
Commands: [analyze-process, dump-process, analyze-hprof, strip-hprof]
56+
57+
analyze-process: Dumps the heap for the provided process name, pulls the hprof file and analyzes it.
58+
USAGE: analyze-process PROCESS_PACKAGE_NAME
59+
60+
dump-process: Dumps the heap for the provided process name and pulls the hprof file.
61+
USAGE: dump-process PROCESS_PACKAGE_NAME
62+
63+
analyze-hprof: Analyzes the provided hprof file.
64+
USAGE: analyze-hprof HPROF_FILE_PATH
65+
66+
strip-hprof: Replaces all primitive arrays from the provided hprof file with arrays of zeroes.
67+
USAGE: strip-hprof HPROF_FILE_PATH
68+
```
69+
70+
## Shark code examples
71+
72+
### Reading records in a hprof file
73+
74+
```groovy
75+
dependencies {
76+
implementation 'com.squareup.leakcanary:shark-hprof:$sharkVersion'
77+
}
78+
```
2479

2580
```kotlin
2681
// Prints all class and field names
@@ -34,13 +89,19 @@ Hprof.open(heapDumpFile)
3489
}
3590
```
3691

37-
### Navigating the heap object graph with shark-graph
92+
### Navigating the heap object graph
93+
94+
```groovy
95+
dependencies {
96+
implementation 'com.squareup.leakcanary:shark-graph:$sharkVersion'
97+
}
98+
```
3899

39100
```kotlin
40101
// Prints all thread names
41102
Hprof.open(heapDumpFile)
42103
.use { hprof ->
43-
val heapGraph = HeapGraph.indexHprof(hprof)
104+
val heapGraph = HprofHeapGraph.indexHprof(hprof)
44105
val threadClass = heapGraph.findClassByName("java.lang.Thread")!!
45106
val threadNames: Sequence<String> = threadClass.instances.map { instance ->
46107
val nameField = instance["java.lang.Thread", "name"]!!
@@ -50,7 +111,13 @@ Hprof.open(heapDumpFile)
50111
}
51112
```
52113

53-
### Generating a heap analysis report with shark
114+
### Generating a heap analysis report
115+
116+
```groovy
117+
dependencies {
118+
implementation 'com.squareup.leakcanary:shark:$sharkVersion'
119+
}
120+
```
54121

55122
```kotlin
56123
val heapAnalyzer = HeapAnalyzer(AnalyzerProgressListener.NONE)
@@ -61,15 +128,21 @@ val analysis = heapAnalyzer.checkForLeaks(
61128
val field = instance["com.example.ThingWithLifecycle", "destroyed"]!!
62129
val destroyed = field.value.asBoolean!!
63130
if (destroyed) {
64-
reportLeaking(reason = "ThingWithLifecycle.destroyed = true")
131+
leakingReasons += "ThingWithLifecycle.destroyed = true"
65132
}
66133
}
67134
})
68135
)
69136
println(analysis)
70137
```
71138

72-
### Generating an Android heap analysis report with shark-android
139+
### Generating an Android heap analysis report
140+
141+
```groovy
142+
dependencies {
143+
implementation 'com.squareup.leakcanary:shark-android:$sharkVersion'
144+
}
145+
```
73146

74147

75148
```kotlin

docs/upgrading-to-leakcanary-2.0.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ val objectWatcher: ObjectWatcher = AppWatcher.objectWatcher
7272

7373
## Compile errors because RefWatcher is used in release code
7474

75-
If you were using `RefWatcher` in non debug code, you now get a compile error because the no-op artifact is gone. `ObjectWatcher` now lives in the `object-watcher` artifact, which is suitable for production. You have two options:
75+
If you were using `RefWatcher` in non debug code, you now get a compile error because the no-op artifact is gone. [ObjectWatcher](/api/leakcanary-object-watcher/leakcanary/-object-watcher/) now lives in the `object-watcher` artifact, which is suitable for production. You have two options:
7676

7777
### Option 1: Add `object-watcher-android` to release builds.
7878

@@ -82,7 +82,7 @@ dependencies {
8282
}
8383
```
8484

85-
* It will automatically keep weak references to destroyed activities, fragments, and any instance you pass to `ObjectWatcher`.
85+
* It will automatically keep weak references to destroyed activities, fragments, and any instance you pass to [AppWatcher.objectWatcher](/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/object-watcher/).
8686
* It will not trigger heap dumps or anything else that LeakCanary does.
8787
* It's very little code and should have a no impact on your release app.
8888
* You can use it to count how many objects are retained, for example to add metadata to OutOfMemoryError crashes:
@@ -112,7 +112,7 @@ class RealObjectWatcher : MaybeObjectWatcher {
112112
}
113113
```
114114

115-
Use MaybeObjectWatcher.None in release code and RealObjectWatcher in debug code.
115+
Use `MaybeObjectWatcher.None` in release code and `RealObjectWatcher` in debug code.
116116

117117
## Configuring LeakCanary
118118

@@ -131,7 +131,7 @@ public class DebugExampleApplication extends ExampleApplication {
131131

132132
### Now
133133

134-
AppWatcher is in charge of detecting retained objects. Its configuration can be updated at any time by replacing `AppWatcher.config`:
134+
AppWatcher is in charge of detecting retained objects. Its configuration can be updated at any time by replacing [AppWatcher.config](/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/config/):
135135

136136
```kotlin
137137
class DebugExampleApplication : ExampleApplication() {
@@ -143,7 +143,7 @@ class DebugExampleApplication : ExampleApplication() {
143143
}
144144
```
145145

146-
LeakCanary is in charge of taking heap dumps and analyzing them. Its configuration can be updated at any time by replacing `LeakCanary.config`:
146+
LeakCanary is in charge of taking heap dumps and analyzing them. Its configuration can be updated at any time by replacing [LeakCanary.config](/api/leakcanary-android-core/leakcanary/-leak-canary/config/):
147147

148148
```kotlin
149149
disableLeakCanaryButton.setOnClickListener {

shark-cli/src/main/java/shark/Main.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,22 @@ fun main(args: Array<String>) {
2323
fun printHelp() {
2424
val workingDirectory = File(System.getProperty("user.dir"))
2525

26+
// ASCII art is a remix of a shark from -David "TAZ" Baltazar- and chick from jgs.
2627
SharkLog.d(
2728
"""
28-
LeakCanary CLI
29-
Running in directory $workingDirectory
29+
Shark CLI, running in directory $workingDirectory
30+
31+
^`. .=""=.
32+
^_ \ \ / _ _ \
33+
\ \ { \ | d b |
34+
{ \ / `~~~--__ \ /\ /
35+
{ \___----~~' `~~-_/'-=\/=-'\,
36+
\ /// a `~. \ \
37+
/ /~~~~-, ,__. , /// __,,,,) \ |
38+
\/ \/ `~~~; ,---~~-_`/ \ / \/
39+
/ / '. .'
40+
'._.' _|`~~`|_
41+
/|\ /|\
3042
3143
Commands: [analyze-process, dump-process, analyze-hprof, strip-hprof]
3244

0 commit comments

Comments
 (0)