如何从Java应用内部检测JVM垃圾回收(GC)周期?
解决方案
不需要使用MonitoredVm,JDK内置标准API即可实现GC事件的监听,实现复杂度和注册shutdown hook相当,不需要依赖外部工具、不需要获取本地VM ID,兼容所有主流JDK版本和GC实现。
核心实现逻辑
基于java.lang.management.GarbageCollectorMXBean注册通知监听器,GC完成后会自动触发你自定义的回调逻辑,时序、安全性均满足要求。
标准实现代码示例
import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import javax.management.Notification; import javax.management.NotificationEmitter; import javax.management.NotificationListener; import javax.management.openmbean.CompositeData; import com.sun.management.GarbageCollectionNotificationInfo; public class GcMonitor { public static void registerGcListener() { // 遍历当前JVM所有GC对应的MXBean实例 for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) { NotificationEmitter emitter = (NotificationEmitter) gcBean; // 注册GC事件监听器 emitter.addNotificationListener(new NotificationListener() { @Override public void handleNotification(Notification notification, Object handback) { // 筛选GC完成事件 if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData()); // 可按需获取GC相关参数 String gcName = gcInfo.getGcName(); // GC类型,如G1 Young Generation、ZGC String gcType = gcInfo.getGcAction(); // GC分类,如minor GC、major GC long costMs = gcInfo.getGcInfo().getDuration(); // GC耗时,单位毫秒 // 此处填入自定义业务逻辑即可 System.out.printf("GC完成:%s,类型:%s,耗时%dms%n", gcName, gcType, costMs); } } }, null, null); } } public static void main(String[] args) { // 应用启动时注册一次监听器即可 registerGcListener(); // 后续执行你的业务代码 } }
兼容受限环境的反射实现
如果运行环境不允许引用com.sun.management包下的类,可通过反射直接解析通知内容,无需依赖额外类:
@Override public void handleNotification(Notification notification, Object handback) { if ("com.sun.management.gc.notification".equals(notification.getType())) { Object userData = notification.getUserData(); try { Method getMethod = userData.getClass().getMethod("get", String.class); String gcName = (String) getMethod.invoke(userData, "gcName"); Object gcInfo = getMethod.invoke(userData, "gcInfo"); long duration = (Long) gcInfo.getClass().getMethod("getDuration").invoke(gcInfo); // 业务逻辑处理 } catch (Exception e) { // 按需处理异常 } } }
内容的提问来源于stack exchange,提问作者JayC667
相关产品推荐
相关产品推荐

