gpt4 book ai didi

java - 以编程方式捕获 Full GC 计数

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:11:18 24 4
gpt4 key购买 nike

我正在 try catch 在我们的 Java 应用程序中发生的完整 GC。到目前为止,我有两种方法,都有缺陷:

  1. 每隔 x 秒轮询一次 GarbageCollectorMXBean 对象,然后尝试提取自上次轮询以来的 GC 时间和 GC 计数,并尝试检测 GC 发生的时间。不幸的是,我们不知道它是否是 Full GC。
  2. 使用 javax.management.NotificationListener,订阅 GarbageCollectorMXBean 通知。理论上,当 GC 发生时,应用程序将收到通知,并带有文本“主要 GC 结束”和“次要 GC 结束”以及原因。这种方法的缺陷是持续时间似乎非常不正确(有时显示 898 秒,而 GC 日志将显示 .2 秒)并且存在神秘的情况“No GC”,这似乎表明实际上没有执行 GC(如gc 日志中没有条目)。

可以采用混合方法,当我收到 GC 通知时可以查询 GC MXBeans,然后检查是否已执行 GC。这样做的缺点是,No GC 原因可能仍然会在“major GC”结束时触发,导致逻辑更加复杂。

我真正想要的是应用程序因 GC 操作而暂停的总时间。我认为捕获一个完整的 GC 足以表明应用程序已停止一段时间,因此如果我们检测到频繁的 GC,我们知道使用量很大或者应用程序将很快耗尽内存。有没有更好的方案来检测GC时间和是否有full GC?

编辑:明确地说,我想在给定的 JVM 中捕获此信息。这个 JVM 由一个单独的团队控制,我们没有必要控制他们将设置的 JVM 参数,我们只能提出建议。这个想法类似于飞行记录器,但不是实时向管理员提供信息。

最佳答案

您可以监听 GC 通知。请参阅下面的代码。

我在这里交叉发布这个答案,因为它看起来很相关。基于pointers given by @the8472 in this question我制作了一个更完整的示例,用于从 JVM 内部记录 GC(并因此检测/计算它)。我希望这会节省一些时间:)

package fi.pelam.gclogutil;
import java.lang.management.*;
import java.util.Map;
import javax.management.openmbean.CompositeData;
import javax.management.*;

import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GcInfo;

public class GcLogUtil {
static public void startLoggingGc() {
// http://www.programcreek.com/java-api-examples/index.php?class=javax.management.MBeanServerConnection&method=addNotificationListener
// https://docs.oracle.com/javase/8/docs/jre/api/management/extension/com/sun/management/GarbageCollectionNotificationInfo.html#GARBAGE_COLLECTION_NOTIFICATION
for (GarbageCollectorMXBean gcMbean : ManagementFactory.getGarbageCollectorMXBeans()) {
try {
ManagementFactory.getPlatformMBeanServer().
addNotificationListener(gcMbean.getObjectName(), listener, null,null);
} catch (Exception e) {
e.printStackTrace();
}
}
}

static private NotificationListener listener = new NotificationListener() {
@Override
public void handleNotification(Notification notification, Object handback) {
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
// https://docs.oracle.com/javase/8/docs/jre/api/management/extension/com/sun/management/GarbageCollectionNotificationInfo.html
CompositeData cd = (CompositeData) notification.getUserData();
GarbageCollectionNotificationInfo gcNotificationInfo = GarbageCollectionNotificationInfo.from(cd);
GcInfo gcInfo = gcNotificationInfo.getGcInfo();
System.out.println("GarbageCollection: "+
gcNotificationInfo.getGcAction() + " " +
gcNotificationInfo.getGcName() +
" duration: " + gcInfo.getDuration() + "ms" +
" used: " + sumUsedMb(gcInfo.getMemoryUsageBeforeGc()) + "MB" +
" -> " + sumUsedMb(gcInfo.getMemoryUsageAfterGc()) + "MB");
}
}
};

static private long sumUsedMb(Map<String, MemoryUsage> memUsages) {
long sum = 0;
for (MemoryUsage memoryUsage : memUsages.values()) {
sum += memoryUsage.getUsed();
}
return sum / (1024 * 1024);
}
}

关于java - 以编程方式捕获 Full GC 计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27871404/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com