如何在不使用GC日志的情况下在Java程序中打印巨大的分配?

问题描述 投票:0回答:1

我目前正在开发一个使用巨大分配和区域的 Java 应用程序。通常,我会使用 GC(垃圾收集)日志来监视这些分配和区域。然而,在这种情况下,我正在寻找替代方法来打印 JVM 中的巨大分配,就像我可以在 memoryPoolMXBean 中看到 Eden/Survivor/Old Spaces 的属性一样。

GC日志:

G1 Eden Space memory used: 0 (0.0%)
G1 Old Gen memory used: 1077833728 (82.1%)
G1 Survivor Space memory used: 262128 (12.5%)
[0.905s] [info] [gc, start
] GC (2) Pause Young (Concurrent Start) (G1 Humongous Allocation)
[0.906s] [info] [gc, task [0.907s] [info] [gc, phases
1 GC(2) Using 8 workers of 8 for evacuation
1 GC (21
[0.907s] [info] [g, phases
GC (2)
Merge Heap Roots: 0.1ms
[0.907s] [info] [gc, phases
GC (2)
Evacuate Collection Set: 0.4ms
[0.907s] [info] [gc, phases
GC (2)
Post Evacuate Collection Set: 0.3ms
[0.907s] [info] [gc, phases
] GC (2)
Other: 0.3ms
[0.907s] [info] [gc, heap
] GC (2) Eden regions: 1->0 (32)
[0.907s] [info] [gc, heap
GC(2) Survivor regions: 1->1(2)
[0.907s] [info] [gc, heap
GC (2) Old regions: 0->0
[0.907s] [info] [gc, heap
] GC (2) ArchIve regIOnS: 2->2
[0.907s] [infol [gc, heap
] GC (2) Humongous regions: 513->513
[0.907s] [info] [g, metaspace] GC(2) Metaspace: 705K(896K)->705K (396K) NonClass: 637K(768K)->637K(768K) Class: 68K(128K) ->68K(128K)
[0.907s] [infol [ac
GC (2)
Pause Young (Concurrent Start) (G1 Humongous Allocation) 1029M->1028M(1284M) 1.180ms

以下是我的具体情况:

  • 我有一个 Java 程序正在经历巨大的分配。

  • 我熟悉使用 GC 日志来监控这些分配和区域。

有没有办法在不使用GC日志的情况下打印或监视Java程序中巨大的分配和区域?任何能够以编程方式提供此信息的 API 或技术将不胜感激。

谢谢你

java cassandra jvm garbage-collection mbeans
1个回答
0
投票

您可以使用 JFR Event Streaming API 以编程方式处理

jdk.ObjectAllocationOutsideTLAB
事件。已知大于堆区域大小一半的分配是巨大的。

这是一个例子:

import com.sun.management.HotSpotDiagnosticMXBean;
import jdk.jfr.consumer.RecordingStream;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ThreadLocalRandom;

public class HumongousAlloc {

    private static long getRegionSize() {
        try {
            HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
                    ManagementFactory.getPlatformMBeanServer(),
                    "com.sun.management:type=HotSpotDiagnostic",
                    HotSpotDiagnosticMXBean.class);
            return Long.parseLong(bean.getVMOption("G1HeapRegionSize").getValue());
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private static void handleAllocations() {
        long humongousAllocationSize = getRegionSize() / 2;

        try (var rs = new RecordingStream()) {
            rs.enable("jdk.ObjectAllocationOutsideTLAB");
            rs.onEvent("jdk.ObjectAllocationOutsideTLAB", event -> {
                long allocationSize = event.getValue("allocationSize");
                if (allocationSize >= humongousAllocationSize) {
                    System.out.println("Humongous allocation: " + event);
                }
            });
            rs.start();
        }
    }

    static volatile Object sink;

    public static void main(String[] args) {
        new Thread(HumongousAlloc::handleAllocations).start();

        while (true) {
            int size = 1 << ThreadLocalRandom.current().nextInt(24);
            sink = new byte[size];
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.