Programmatically Generate Java Heap Dump In Spring Application

Md Ariful Islam Rana
2 min readAug 4, 2019

--

Why we need this?

Though the best practice to generate heap dump in production environment by providing following JVM argument at application startup -

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>

but I experienced in some cases it’s not possible to generate heap dump in this way. Production environment is used by lots of users. It becomes very slow when memory leaks happens and no one will wait for generating heap dump. So, make it usable, application needs to restart quickly.

Common scenario of memory leak is, it usages excessive memory compare to memory usage of its whole runtime. Most of the time application usages less memory of assigned maximum heap size. Note that, production environment has set much more memory than needed most of the time. So, when we found memory usage more than two third, then we almost certain that memory leak happens.

Another use case to generate heap dump programmatically is, may be developer want to check which process consumes how much memory. So in that case it obvious to generate heap dump programmatically.

Implementation

In Spring framework, we can generate a cron job that may run every five minutes (or any custom time) to check if the heap dump generation condition meet, and if it meets criteria, then application generate heap dump without doing hampers to any other features.

Check the following Java class -

import com.sun.management.HotSpotDiagnosticMXBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.management.MBeanServer;
import java.io.File;
import java.lang.management.ManagementFactory;

@Component
public class HeapDumpGenerator {
private static Boolean generated = Boolean.FALSE;

@Scheduled(cron = "0 0/5 * * * *")
public void execute() {
if (allowToGenerate()) {
generateHeapDump();
}
}
/**
*
In this method, I checked memory usage and depends
* on memory usage, I generated heap dump,
* you have to put your criteria
*/

private boolean allowToGenerate() {
// Want to generate once?
// If not remove this block
if (generated) {
return Boolean.FALSE;
}
// Assumed default hard coded value,
// but it should load from application configuration file
Long thresholdInMB = 8192;

Long usedMemoryInMB = (Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory())
/ 1024 / 1024;

return usedMemoryInMB > thresholdInMB;
}

private void generateHeapDump() {
MBeanServer mBeanServer = ManagementFactory.
getPlatformMBeanServer();
String dumpFilePath = System.getProperty("user.home") +
File.separator + "heap-dumps"+ File.separator +
"dumpfile_" + System.currentTimeMillis() + ".hprof";
try {
HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean =
ManagementFactory.newPlatformMXBeanProxy(
mBeanServer,
"com.sun.management:type=HotSpotDiagnostic",
HotSpotDiagnosticMXBean.class);
hotSpotDiagnosticMXBean.dumpHeap(
dumpFilePath, Boolean.TRUE);
// will not generate again
generated = Boolean.TRUE;
} catch (Exception e) {
//log exception
}
}
}

The method allowToGenerate() checks if the application is going to generate dump file or not. Here, I usages memory consumption to generate heap dump. The generateHeapDump() method is the core one which generate dump file. Note that, dumpFilePath is the fully qualified name of the dump file.

In this way, we can generate heap dump easily and can analysis memory leak or other scenarios. Note that, this isn’t the alternative of JVM arguments of heap dump. In production environment, we should still use that arguments.

--

--

Md Ariful Islam Rana
Md Ariful Islam Rana

No responses yet