微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 用于确定JVM即将进入内存/ GC问题的有用指标

我有一个 Scala数据处理应用程序,95%的时间可以处理在内存中抛出的数据.剩下的5%如果没有被选中,通常不会打到OutOfMemoryError,而是进入一个主要的GC的周期,尖锐的cpu,防止后台线程执行,如果它甚至完成,只要它是10x-50x有足够的记忆力

我已经实现了可以将数据刷新到磁盘的系统,并将其视为内存中的迭代器.这通常比记忆慢一个数量级,但对于这5%的情况来说足够了.我目前正在通过追踪数据处理涉及的各种集合的大小的集合上下文的最大大小的启发式触发.这是有效的,但实际上只是一个独特的经验门槛.

我更愿意对JVM进行接近上述不良状态的反应,并在当时刷新到磁盘.我已经尝试看内存,但找不到正确的eden,old等组合来可靠地预测死亡螺旋.我也试过只是观察主要GC的频率,但是似乎还有一个广泛的“太保守”到“太晚”了.

任何用于判断JVM运行状况和检测故障状态的资源将不胜感激.

解决方法

一种可靠的方法是在GC事件上注册通知侦听器,并在所有Full GC事件之后检查内存健康状况.在完整的GC事件之后,使用的内存是您实际的实时数据集.如果你在这个时间点的空闲内存很低,可能是时间开始闪烁到磁盘.

这样,您可以避免在您无法知道何时完成GC时检查内存,例如使用MEMORY_THRESHOLD_EXCEEDED通知类型时,会发生误报.

您可以注册通知侦听器,并使用以下代码处理全部GC事件:

// ... standard imports ommitted
import com.sun.management.GarbageCollectionNotificationInfo;

public static void installGCMonitoring() {
    List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
    for (GarbageCollectorMXBean gcBean : gcBeans) {
        NotificationEmitter emitter = (NotificationEmitter) gcBean;
        NotificationListener listener = notificationListener();
        emitter.addNotificationListener(listener,null,null);
    }
}

private static NotificationListener notificationListener() {
    return new NotificationListener() {
        @Override
        public void handleNotification(Notification notification,Object handback) {
            if (notification.getType()
                    .equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
                GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo
                        .from((CompositeData) notification.getUserData());
                String gctype = info.getGcAction();
                if (gctype.contains("major")) {
                    // We are only interested in full (major) GCs
                    Map<String,MemoryUsage> mem = info.getGcInfo().getMemoryUsageAfterGc();
                    for (Entry<String,MemoryUsage> entry : mem.entrySet()) {
                        String memoryPoolName = entry.getKey();
                        MemoryUsage memdetail = entry.getValue();
                        long memmax = memdetail.getMax();
                        long memUsed = memdetail.getUsed();
                        // Use the memmax/memUsed of the pool you are interested in (probably old gen)
                        // to determine memory health.
                    }
                }
            }
        }
    };
}

Cred到this文章,我们第一次得到这个想法.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐