I have a sudden memory leak which occurs fairly instantaneously so I must catch the dump with HeapDumpOnOutOfMemoryError. But to see what really caused this massive memory spike I need to take a baseline first, and I use jcmd $pid GC.heap_dump baseline.hprof
for that. When the crash heap dump gets created, and I say jhat -baseline baseline.hprof java_pid1234.hprof
then I do not get the baseline subtracted properly, it makes no difference whether or not I add the -baseline option. The output says it does the subtraction:
Snapshot resolved.
Reading baseline snapshot...
Dump file created Sun Mar 01 18:42:47 EST 2020
Resolving 10680567 objects...
Discovering new objects...
Started HTTP server on port 9999
Server is ready.
but it makes no difference! Why is that? In 10-year old issues reported here Why doesn't the -baseline option of jhat work? it said stuff about heap dump generated with jmap is incompatible but I'm not using jmap.
Is there some way I can invoke the exact same code as this HeapDumpOnOutOfMemoryError uses to create the baseline?
I think I will try to just trigger this memory dump twice. But it's very inconvenient, and [UPDATE] this doesn't even work! This memory dump is only created once. I created this function:
public static void forceOutOfMemory() {
byte a[][] = new byte[100][];
for(int i = 0; i < 100 ; i++) {
System.err.println("FOOM-" + i);
a[i] = new byte[1000000000];
}
}
and when I run this once it does this:
FOOM-0
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12360.hprof ...
Heap dump file created [17509743 bytes in 0.085 secs]
... exception thrown
but the second time I call it it did this:
FOOM-0
... exception thrown
so that leaves me stuck!
PS: please don't tell me about Eclipse or some other IDE, I am running essentially headless.
UPDATE: I still want to know why that is so, because it's annoying. But I have written myself a workaround:
public static void dumpHeap(String name) throws Exception {
java.util.List<com.sun.management.HotSpotDiagnosticMXBean> list = java.lang.management.ManagementFactory.getPlatformMXBeans(com.sun.management.HotSpotDiagnosticMXBean.class);
java.io.File dump = new java.io.File(name + ".hprof");
if(dump.exists())
dump.delete();
System.out.println("Dumping to file: " + dump.getAbsolutePath());
list.get(0).dumpHeap(dump.getAbsolutePath(), true);
}
This works because it uses the same dumpHeap function that the OutOfMemory thing also uses.
ANOTHER UPDATE: This seemed to work, but for my purpose it still doesn't work. Oracle Java 1.8 on Windows. It was extremely frustrating. I got nothing for all of this work. I still see all the baseline data in the jhat histogram.