1

我有一个突然的内存泄漏,它发生在相当瞬间,所以我必须使用 HeapDumpOnOutOfMemoryError 捕获转储。但是要查看真正导致这种巨大内存峰值的原因,我需要先获取一个基线,然后我会使用jcmd $pid GC.heap_dump baseline.hprof它。当创建崩溃堆转储时,我说jhat -baseline baseline.hprof java_pid1234.hprof我没有正确减去基线,是否添加 -baseline 选项没有区别。输出说它做了减法:

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.

但这没有区别!这是为什么?在此处报告的 10 年前的问题中 为什么 jhat 的 -baseline 选项不起作用?它说有关使用 jmap 生成的堆转储的内容不兼容,但我没有使用 jmap。

有什么方法可以调用与此 HeapDumpOnOutOfMemoryError 用于创建基线的代码完全相同的代码吗?

我想我会尝试触发这个内存转储两次。但这很不方便,而且 [更新] 这甚至不起作用!此内存转储仅创建一次。我创建了这个函数:

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];        
    }
}

当我运行它时,它会这样做:

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

但我第二次称它为:

FOOM-0
... exception thrown

所以这让我卡住了!

PS:请不要告诉我有关 Eclipse 或其他 IDE 的信息,我基本上是在无头运行。

更新:我仍然想知道为什么会这样,因为它很烦人。但我给自己写了一个解决方法:

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);     
}   

这是有效的,因为它使用 OutOfMemory 也使用的相同 dumpHeap 函数。

另一个更新:这似乎有效,但出于我的目的,它仍然不起作用。Windows 上的 Oracle Java 1.8。这非常令人沮丧。所有这些工作我一无所获。我仍然在 jhat 直方图中看到所有基线数据。

4

0 回答 0