是的,JVM为您提供了足够的工具来检索G1的此类信息。例如,您可以使用类似此类的内容来打印有关垃圾回收的所有详细信息(只需调用):MemoryUtil.startGCMonitor()
public class MemoryUtil {
private static final Set<String> heapRegions;
static {
heapRegions = ManagementFactory.getMemoryPoolMXBeans().stream()
.filter(b -> b.getType() == MemoryType.HEAP)
.map(MemoryPoolMXBean::getName)
.collect(Collectors.toSet());
}
private static NotificationListener gcHandler = (notification, handback) -> {
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());
Map<String, MemoryUsage> memBefore = gcInfo.getGcInfo().getMemoryUsageBeforeGc();
Map<String, MemoryUsage> memAfter = gcInfo.getGcInfo().getMemoryUsageAfterGc();
StringBuilder sb = new StringBuilder(250);
sb.append("[").append(gcInfo.getGcAction()).append(" / ").append(gcInfo.getGcCause())
.append(" / ").append(gcInfo.getGcName()).append(" / (");
appendMemUsage(sb, memBefore);
sb.append(") -> (");
appendMemUsage(sb, memAfter);
sb.append("), ").append(gcInfo.getGcInfo().getDuration()).append(" ms]");
System.out.println(sb.toString());
}
};
public static void startGCMonitor() {
for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) {
((NotificationEmitter) mBean).addNotificationListener(gcHandler, null, null);
}
}
public static void stopGCMonitor() {
for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) {
try {
((NotificationEmitter) mBean).removeNotificationListener(gcHandler);
} catch(ListenerNotFoundException e) {
// Do nothing
}
}
}
private static void appendMemUsage(StringBuilder sb, Map<String, MemoryUsage> memUsage) {
memUsage.entrySet().forEach((entry) -> {
if (heapRegions.contains(entry.getKey())) {
sb.append(entry.getKey()).append(" used=").append(entry.getValue().getUsed() >> 10).append("K; ");
}
});
}
}
在此代码中,为您提供了足够的信息,以将次要集合与主要/混合集合分开。gcInfo.getGcAction()
但是,使用您的方法(带有阈值)到G1有一个重要的警告。G1 中的单个混合集合通常只影响几个旧的 gen 区域 - 许多区域足以释放足够的内存量,但不会太多以保持 GC 暂停较低。因此,在G1中混合收集后,您无法确定所有垃圾都已消失。因此,您需要找到更复杂的策略来检测内存泄漏(可能基于集合频率,从多个集合中收集统计信息等)。