2

Obtaining heap dump on OutOfMemoryError with Quarkus native

 1 week ago
source link: https://quarkus.io/blog/heapdump-oome-native/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Blog Obtaining heap dump on OutOfMemoryError with Quarkus native

April 23, 2024 #native

Obtaining heap dump on OutOfMemoryError with Quarkus native

Starting with GraalVM for JDK 21, native executables can run with the -XX:+HeapDumpOnOutOfMemoryError option to generate a heap dump when a java.lang.OutOfMemoryError is thrown. In this blog post we will explore how to use the flag, we will inspect what a GraalVM Native Image heap dump looks like and how it compares with one produced by HotSpot.

Note: The heap of GraalVM Native Image executables has both read-only and read-write segments. The read-only part is referred to as the "image heap" and contains the data pre-initialized during the image build to help speed up start-up time. The read-write part is where allocations at runtime are made. Therefore, heap dumps generated at runtime will contain content from both the "image heap" and the read-write heap.

To see this flag in action, we need to manufacture a situation where a Quarkus application runs out of memory. One easy way to achieve this is to configure the application with a garbage collector that doesn’t do any memory reclamation, i.e. the Epsilon GC. Once the Quarkus application is running with Epsilon GC, apply some load and within a short space of time it will run out of memory and produce a heap dump.

Let’s do this using a Quarkus application that simply responds to an HTTP endpoint request as a starting point. The sample application can be downloaded from code.quarkus.io using a browser or via the command line:

Next, build a Quarkus native executable with GraalVM for JDK 21 configuring it to use Epsilon GC:

Note: The GC selection needs to be done at build time for Quarkus native applications.

While the Quarkus native executable is being produced you will be able to observe that GC is indeed configured to be EpsilonGC:

Once the build completes, start Quarkus with -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError. The latter forces the application to shutdown when an OutOfMemoryError occurs rather than leave the process in an indeterminate state:

Next, apply some load to the HTTP endpoint exposed by the Quarkus application, for example using curl in a bash loop:

Switching to the Quarkus console, an OutOfMemoryError would be observed along with some messages indicating that a heap dump is being produced:

Multiple graphical tools exist out there to inspect heap dumps, such as VisualVM, Eclipse Memory Analyzer (MAT), etc., but some new ones are also available that you can run in the command line to get a quick picture of the heap dump, for example Java Object Layout (JOL):

The presence of SubstrateVM, the VM that powers native images built with GraalVM, can be clearly observed because of the instances of com.oracle.svm.core.monitor.JavaMonitor present in the heap dump. What would the heap dump look like if we repeat exactly the same exercise but instead we use Quarkus JVM mode? Let’s see:

Rebuild the Quarkus app for JVM mode and run it with Epsilon GC:

After applying the same load, you would observe the heap dump being generated in JVM mode as well:

And this is what the heap dump looks like with JOL:

As expected, no SubstrateVM classes are present in this heap dump, leaving only Quarkus, Vert.x and OpenJDK types in the heap dump.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK