Heap Dumper & Heap Analyzer
Introduction
Heap Dumper is a tool that allows to get a snapshot of the heap of an Application running on the Simulator or on a device.
The Heap Analyzer is a set of tools to help developers understand the contents of the Java heap and find problems such as memory leaks. For its part, the Heap Analyzer IDE plugin is able to visualize dump files. It helps you analyze their contents thanks to the following features:
memory leaks detection
objects instances browse
heap usage optimization (using immortal or immutable objects)
The Heap
The heap is a memory area used to hold Java objects created at runtime. Objects persist in the heap until they are garbage collected. An object becomes eligible for garbage collection when there are no longer any references to it from other objects.
Heap Dump
A heap dump is an XML file (with the .heap
extension) that provides a snapshot of the heap contents at the moment the file is created.
It contains a list of all the instances of both class and array types that exist in the heap.
For each instance, it records:
The time at which the instance was created
The thread that created it
The method that created it
For instances of class types, it also records:
The class
The values in the instance’s non-static fields
For instances of array types, it also records:
The type of the contents of the array
The contents of the array
For each referenced class type, it records the values in the static fields of the class.
Heap Analyzer Tools
The Heap Analyzer is an Eclipse IDE plugin that adds three tools to the MicroEJ environment.
Tool name
Number of input files
Purpose
Heap Viewer
1
Shows what instances are in the heap, when they were created, and attempts to identify problem areas
Progressive Heap Usage
1 or more
Shows how the number of instances in the heap has changed over time
Compare
2
Compares two heap dumps, showing which objects were created, or garbage collected, or have changed values
Heap Dumper
The Heap Dumper generates .heap
files. There are two implementations:
- the one integrated to the Simulator: it directly dumps .heap
files from the Java heap.
- the Heap Dumper tool: it generates .heap
files from .hex
files that must be manually retrieved from the device.
The heap dump should be performed after a call to System.gc() to exclude discardable objects.
Simulator
In order to generate a Heap dump of an Application running on the Simulator:
Set the
s3.inspect.heap
Application properties totrue
.Update your Application code to call the System.gc() method where you need a Heap dump.
run the Application on the Simulator.
When the System.gc() method is called:
if it is called from the Application, the
.heap
file is generated in thebuild/output/<fqnMainClass>/heapDump/
folder of the project, where<fqnMainClass>
is the Fully Qualified Name of the Application Main class, for example (com.mycompany.Main
).if it is called from a test class, the
.heap
file is generated in thebuild/testsuite/output/<buildDate>/bin/<fqnMainClass>/heapDump/
folder of the project, where<fqnMainClass>
is the Fully Qualified Name of the generated Main class and<buildDate>
is the date of the test execution, for example (build/testsuite/output/20240625-1605-24/bin/com.mycompany._AllTests_MyTest/heapDump/
).
Device
In order to generate a Heap dump of an Application running on a device:
Update your Application code to call the System.gc() method where you need a Heap dump.
Build the Executable and deploy it on the device.
Start a debug session.
Add a breakpoint to
LLMJVM_on_Runtime_gc_done
Core Engine hook. This function is called by the Core Engine when System.gc() method is done. Alternatively, if you are experiencing out of memory errors, you can directly add a breakpoint to theLLMJVM_on_OutOfMemoryError_thrown
Core Engine hook.Resume the execution until the breakpoint is reached. You are now ready to dump the memory. Next steps are:
Note
Core Engine hooks may have been inlined by the third-party linker. If the symbol is not accessible to the debugger, you must declare them in your VEE Port:
void LLMJVM_on_Runtime_gc_done(){
//No need to add code to the function
}
void LLMJVM_on_OutOfMemoryError_thrown(){
//No need to add code to the function
}
Retrieve the .hex
file from the device
If you are in a Mono-Sandbox context, you only have to dump the Core Engine heap section. Here is an example of GDB commands:
b LLMJVM_on_Runtime_gc_done b LLMJVM_on_OutOfMemoryError_thrown continue dump ihex memory heap.hex &_java_heap_start &_java_heap_end
You now have the .hex
file and need to extract the Heap dump.
If you are in a Multi-Sandbox context, the following sections must be dumped additionally:
the installed features table.
dump ihex memory &java_features_dynamic_start &java_features_dynamic_end
the installed features sections. These are specific to your VEE Port, depending on the LLKERNEL implementation <LLKF-API-SECTION>.
dump ihex memory <installed features_start_adress> <installed features_end_adress>
To simplify the dump commands, you can also consider the following options :
either dump the entire memory where microej runtime and code sections are linked,
or generate the VEE memory dump script which will dump all the required sections instead.
Note
In a Mono-Sandbox context, use
1_java_heap.hex
.In a Multi-Sandbox context, merge (at least)
1_java_heap.hex
and9_installed_features.hex
with:copy /b 1_java_heap.hex + 9_installed_features.hex memory.hex
Get-Content 1_java_heap.hex, 9_installed_features.hex | Set-Content memory.hex
cat 1_java_heap.hex 9_installed_features.hex > memory.hex
Extract the Heap dump from the .hex
file
In order to extract the Heap dump from an .hex
file,
run the execTool
Gradle task with the tool name heapDumperPlatform
:
./gradlew execTool --name=heapDumperPlatform \
--toolProperty=output.name="application.heap" \
--toolProperty=application.filename="../../executable/application/application.out" \
--toolProperty=heap.filename="/path/to/memory.hex" \
--toolProperty=additional.application.filenames="" \
--console plain
If you are in a Multi-Sandbox context, you have to include the .fodbg
files and additional hex files:
./gradlew execTool --name=heapDumperPlatform \
--toolProperty=output.name="application.heap" \
--toolProperty=application.filename="../../executable/application/application.out" \
--toolProperty=heap.filename="/path/to/memory.hex" \
--toolProperty=additional.application.filenames="/path/to/app1.fodbg;/path/to/app2.fodbg..." \
--toolProperty=additional.memory.filenames="/path/to/additonal1.hex;/path/to/additional2.hex..." \
--console plain
You can find the list of available options below:
Name |
Description |
Default |
---|---|---|
|
Specify the full path of the Executable file, a full linked ELF file. |
Not set |
|
Specify the full path of Feature files with debug information ( |
Not set |
|
Specify the full path of heap memory dump, in Intel Hex format. |
Not set |
|
Specify the full path of additional memory files in Intel Hex format (Installed Feature areas, Dynamic Features table, …). |
Not set |
|
Name of the extracted Heap dump file. |
|
Heap Viewer
To open the Heap Viewer tool, select a heap dump XML file in the Package Explorer, right-click on it and select Open With > Heap Viewer
Alternatively, right-click on it and select Heap Analyzer > Open heap viewer.
This will open a Heap Viewer tool window for the selected heap dump [1].
The Heap Viewer works in conjunction with two views:
The Outline view
The Instance Browser view
These views are described below.
The Heap Viewer tool has three tabs, each described below.
Outline View
The Outline view shows a list of all the types in the heap dump, and for each type shows a list of the instances of that type. When an instance is selected it also shows a list of the instances that refer to that instance. The Outline view is opened automatically when an Heap Viewer is opened.
Instance Browser View
The Instance Browser view opens automatically when a type or instance is selected in the Outline view.
It has two modes, selected using the buttons in the top right corner of the view.
In Fields
mode it shows the field values for the selected type or instance,
and where those fields hold references it shows the fields of the referenced instance, and so on.
In Reference
mode it shows the instances that refer to the selected instance, and the instances that refer to them, and so on.
Heap Usage Tab
The Heap usage page of the Heap Viewer displays four bar charts. Each chart divides the total time span of the heap dump (from the time stamp of the earliest instance creation to the time stamp of the latest instance creation) into a number of periods along the x axis, and shows, by means of a vertical bar, the number of instances created during the period.
The top-left chart shows the total number of instances created in each period, and is the only chart displayed when the Heap Viewer is first opened.
When a type or instance is selected in the Outline view the top-right chart is displayed. This chart shows the number of instances of the selected type created in each time period.
When an instance is selected in the Outline view the bottom-left chart is displayed. This chart shows the number of instances created in each time period by the thread that created the selected instance.
When an instance is selected in the Outline view the bottom-right chart is displayed. This chart shows the number of instances created in each time period by the method that created the selected instance.
Clicking on the graph area in a chart restricts the Outline view to just the types and instances that were created during the selected time period. Clicking on a chart but outside of the graph area restores the Outline view to showing all types and instances [2].
The button Generate graphViz file in the top-right corner of the Heap Usage page generates a file compatible with graphviz (www.graphviz.org).
The section Heap Usage Monitoring shows how to compute the maximum heap usage.
The Outline can also be restored by selecting the All types and instances option on the drop-down menu at the top of the Outline view.
Dominator Tree Tab
The Dominator tree page of the Heap Viewer allows the user to browse the instance reference tree which contains the greatest number of instances. This can be useful when investigating a memory leak because this tree is likely to contain the instances that should have been garbage collected.
The page contains two tree viewers. The top viewer shows the instances that make up the tree, starting with the root. The left column shows the ids of the instances – initially just the root instance is shown. The Shallow instances column shows the number of instances directly referenced by the instance, and the Referenced instances column shows the total number of instances below this point in the tree (all descendants).
The bottom viewer groups the instances that make up the tree either according to their type, the thread that created them, or the method that created them.
Double-clicking an instance in either viewer opens the Instance Browser view (if not already open) and shows details of the instance in that view.
Leak Suspects Tab
The Leak suspects page of the Heap Viewer shows the result of applying heuristics to the relationships between instances in the heap to identify possible memory leaks.
The page is in three parts.
The top part lists the suspected types (classes). Suspected types are classes which, based on numbers of instances and instance creation frequency, may be implicated in a memory leak.
The middle part lists accumulation points. An accumulation point is an instance that references a high number of instances of a type that may be implicated in a memory leak.
The bottom part lists the instances accumulated at an accumulation point.
Progressive Heap Usage
To open the Progressive Heap Usage tool, select one or more heap dump XML files in the Package Explorer, right-click and select Heap Analyzer > Show progressive heap usage
This tool is much simpler than the Heap Viewer described above. It comprises three parts.
The top-right part is a line graph showing the total number of instances in the heap over time, based on the creation times of the instances found in the heap dumps.
The left part is a pane with three tabs, one showing a list of types in the heap dump, another a list of threads that created instances in the heap dump, and the third a list of methods that created instances in the heap dump.
The bottom-left is a line graph showing the number of instances in the heap over time restricted to those instances that match with the selection in the left pane. If a type is selected, the graph shows only instances of that type; if a thread is selected the graph shows only instances created by that thread; if a method is selected the graph shows only instances created by that method.
Compare Heap Dumps
The Compare tool compares the contents of two heap dump files. To open the tool select two heap dump XML files in the Package Explorer, right-click and select Heap Analyzer > Compare
The Compare tool shows the types in the old heap on the left-hand side, and the types in the new heap on the right-hand side, and marks the differences between them using different colors.
Types in the old heap dump are colored red if there are one or more instances of this type which are in the old dump but not in the new dump. The missing instances have been garbage collected.
Types in the new heap dump are colored green if there are one or more instances of this type which are in the new dump but not in the old dump. These instances were created after the old heap dump was written.
Clicking to the right of the type name unfolds the list to show the instances of the selected type.
The combo box at the top of the tool allows the list to be restricted in various ways:
All instances – no restriction.
Garbage collected and new instances – show only the instances that exist in the old heap dump but not in the new dump, or which exist in the new heap dump but not in the old dump.
Persistent instances – show only those instances that exist in both the old and new dumps.
Persistent instances with value changed – show only those instances that exist in both the old and new dumps and have one or more differences in the values of their fields.
Instance Fields Comparison View
The Compare tool works in conjunction with the Instance Fields Comparison view, which opens automatically when an instance is selected in the tool.
The view shows the values of the fields of the instance in both the old and new heap dumps, and highlights any differences between the values.