/
HeapAnalysis.kt
147 lines (133 loc) · 4.21 KB
/
HeapAnalysis.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package shark
import shark.internal.createSHA1Hash
import java.io.File
import java.io.Serializable
/**
* The result of an analysis performed by [HeapAnalyzer], either a [HeapAnalysisSuccess] or a
* [HeapAnalysisFailure]. This class is serializable however there are no guarantees of forward
* compatibility.
*/
sealed class HeapAnalysis : Serializable {
/**
* The hprof file that was analyzed.
*/
abstract val heapDumpFile: File
/**
* The [System.currentTimeMillis] when this [HeapAnalysis] instance was created.
*/
abstract val createdAtTimeMillis: Long
/**
* Total time spent analyzing the heap.
*/
abstract val analysisDurationMillis: Long
}
/**
* The analysis performed by [HeapAnalyzer] did not complete successfully.
*/
data class HeapAnalysisFailure(
override val heapDumpFile: File,
override val createdAtTimeMillis: Long,
override val analysisDurationMillis: Long,
/**
* An exception wrapping the actual exception that was thrown.
*/
val exception: HeapAnalysisException
) : HeapAnalysis()
/**
* The result of a successful heap analysis performed by [HeapAnalyzer].
*/
data class HeapAnalysisSuccess(
override val heapDumpFile: File,
override val createdAtTimeMillis: Long,
override val analysisDurationMillis: Long,
val metadata: Map<String, String>,
/**
* The list of [ApplicationLeak] found in the heap dump by [HeapAnalyzer].
*/
val applicationLeaks: List<ApplicationLeak>,
/**
* The list of [LibraryLeak] found in the heap dump by [HeapAnalyzer].
*/
val libraryLeaks: List<LibraryLeak>
) : HeapAnalysis() {
/**
* The list of [Leak] found in the heap dump by [HeapAnalyzer], ie all [applicationLeaks] and
* all [libraryLeaks] in one list.
*/
val allLeaks: List<Leak>
get() = applicationLeaks + libraryLeaks
}
/**
* A leak found by [HeapAnalyzer], either an [ApplicationLeak] or a [LibraryLeak].
*/
sealed class Leak : Serializable {
/**
* Class name of the leaking object.
* The class name format is the same as what would be returned by [Class.getName].
*/
abstract val className: String
/**
* Shortest path from GC roots to the leaking object.
*/
abstract val leakTrace: LeakTrace
/**
* The number of bytes which would be freed if all references to the leaking object were
* released. Null if the retained heap size was not computed.
*/
abstract val retainedHeapByteSize: Int?
/**
* A unique SHA1 hash that represents this group of leaks.
*
* For [ApplicationLeak] this is based on [LeakTrace.leakCauses] and for [LibraryLeak] this is
* based on [LibraryLeak.pattern].
*/
val groupHash
get() = createGroupHash()
/**
* Returns [className] stripped of any string content before the last period (included).
*/
val classSimpleName: String
get() {
val separator = className.lastIndexOf('.')
return if (separator == -1) className else className.substring(separator + 1)
}
protected abstract fun createGroupHash(): String
}
/**
* A leak found by [HeapAnalyzer], where the only path to the leaking object required going
* through a reference matched by [pattern], as provided to a [LibraryLeakReferenceMatcher]
* instance. This is a known leak in library code that is beyond your control.
*/
data class LibraryLeak(
override val className: String,
override val leakTrace: LeakTrace,
override val retainedHeapByteSize: Int?,
/**
* The pattern that matched one of the references in [leakTrace], as provided to a
* [LibraryLeakReferenceMatcher] instance.
*/
val pattern: ReferencePattern,
/**
* A description that conveys what we know about this library leak.
*/
val description: String
) : Leak() {
override fun createGroupHash() = pattern.toString().createSHA1Hash()
}
/**
* A leak found by [HeapAnalyzer] in your application.
*/
data class ApplicationLeak(
override val className: String,
override val leakTrace: LeakTrace,
override val retainedHeapByteSize: Int?
) : Leak() {
override fun createGroupHash(): String {
return leakTrace.leakCauses
.joinToString(separator = "") { element ->
val referenceName = element.reference!!.groupingName
element.className + referenceName
}
.createSHA1Hash()
}
}