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