xref: /aosp_15_r20/external/perfetto/docs/data-sources/java-heap-profiler.md (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1# Memory: Java heap dumps
2
3NOTE: Capturing Java heap dumps requires Android 11 or higher
4
5See the [Memory Guide](/docs/case-studies/memory.md#java-hprof) for getting
6started with Java heap dumps.
7
8Conversely from [Native heap profiles](native-heap-profiler.md), Java heap dumps
9report full retention graphs of managed objects but not call-stacks. The
10information recorded in a Java heap dump is of the form: _Object X retains
11object Y, which is N bytes large, through its class member named Z_.
12
13Java heap dumps are not to be confused with profiles taken by the
14[Java heap sampler](native-heap-profiler.md#java-heap-sampling)
15
16## UI
17
18Heap graph dumps are shown as flamegraphs in the UI after clicking on the
19diamond in the _"Heap Profile"_ track of a process. Each diamond corresponds to
20a heap dump.
21
22![Java heap dumps in the process tracks](/docs/images/profile-diamond.png)
23
24![Flamegraph of a Java heap dump](/docs/images/java-heap-graph.png)
25
26The native size of certain objects is represented as an extra child node in the
27flamegraph, prefixed with "[native]". The extra node counts as an extra object.
28This is available only on Android 13 or higher.
29
30## SQL
31
32Information about the Java Heap is written to the following tables:
33
34* [`heap_graph_class`](/docs/analysis/sql-tables.autogen#heap_graph_class)
35* [`heap_graph_object`](/docs/analysis/sql-tables.autogen#heap_graph_object)
36* [`heap_graph_reference`](/docs/analysis/sql-tables.autogen#heap_graph_reference)
37
38`native_size` (available only on Android T+) is extracted from the related
39`libcore.util.NativeAllocationRegistry` and is not included in `self_size`.
40
41For instance, to get the bytes used by class name, run the following query.
42As-is this query will often return un-actionable information, as most of the
43bytes in the Java heap end up being primitive arrays or strings.
44
45```sql
46select c.name, sum(o.self_size)
47       from heap_graph_object o join heap_graph_class c on (o.type_id = c.id)
48       where reachable = 1 group by 1 order by 2 desc;
49```
50
51|name                |sum(o.self_size)    |
52|--------------------|--------------------|
53|java.lang.String    |             2770504|
54|long[]              |             1500048|
55|int[]               |             1181164|
56|java.lang.Object[]  |              624812|
57|char[]              |              357720|
58|byte[]              |              350423|
59
60We can use `experimental_flamegraph` to normalize the graph into a tree, always
61taking the shortest path to the root and get cumulative sizes.
62Note that this is **experimental** and the **API is subject to change**.
63From this we can see how much memory is being held by each type of object
64
65For that, we need to find the timestamp and upid of the graph.
66
67```sql
68select distinct graph_sample_ts, upid from heap_graph_object
69```
70
71|graph_sample_ts     |        upid        |
72|--------------------|--------------------|
73|     56785646801    |         1          |
74
75We can then use them to get the flamegraph data.
76
77```sql
78select name, cumulative_size
79from experimental_flamegraph(
80  -- The type of the profile from which the flamegraph is being generated.
81  -- Always 'graph' for Java heap graphs.
82  'graph',
83  -- The timestamp of the heap graph sample.
84  56785646801,
85  -- Timestamp constraints: not relevant and always null for Java heap graphs.
86  NULL,
87  -- The upid of the heap graph sample.
88  1,
89  -- The upid group: not relevant and always null for Java heap graphs.
90  NULL,
91  -- A regex for focusing on a particular node in the heapgraph: for advanced
92  -- use only.
93  NULL
94)
95order by 2 desc;
96```
97
98| name | cumulative_size |
99|------|-----------------|
100|java.lang.String|1431688|
101|java.lang.Class<android.icu.text.Transliterator>|1120227|
102|android.icu.text.TransliteratorRegistry|1119600|
103|com.android.systemui.statusbar.phone.StatusBarNotificationPresenter$2|1086209|
104|com.android.systemui.statusbar.phone.StatusBarNotificationPresenter|1085593|
105|java.util.Collections$SynchronizedMap|1063376|
106|java.util.HashMap|1063292|
107
108## TraceConfig
109
110The Java heap dump data source is configured through the
111[JavaHprofConfig](/docs/reference/trace-config-proto.autogen#JavaHprofConfig)
112section of the trace config.
113
114```protobuf
115data_sources {
116  config {
117    name: "android.java_hprof"
118    java_hprof_config {
119      process_cmdline: "com.google.android.inputmethod.latin"
120      dump_smaps: true
121    }
122  }
123}
124```
125