Java 以编程方式捕获完整GC计数
我试图捕获Java应用程序中出现的完整GCs。到目前为止,我有两种方法,都有缺陷:Java 以编程方式捕获完整GC计数,java,garbage-collection,jvm,Java,Garbage Collection,Jvm,我试图捕获Java应用程序中出现的完整GCs。到目前为止,我有两种方法,都有缺陷: 每x秒轮询一次GarbageCollectorMXBean对象,然后尝试提取自上次轮询以来的GC时间和GC计数,并尝试检测GC发生的时间。不幸的是,我们不知道这是否是一个完整的GC 使用javax.management.NotificationListener,订阅垃圾收集器MXBean通知。理论上,当GC发生时,应用程序将收到通知,其中包含文本“主要GC结束”和“次要GC结束”以及原因。这种方法的缺陷在于持续时
编辑:为了清楚起见,我想在给定的JVM中捕获这些信息。这个JVM由一个单独的团队控制,我们不需要控制他们将设置的JVM参数,我们只能提出建议。这个想法类似于flight recorder,但它可以实时向管理员提供信息。如果您使用热点特定的GC bean,那么您可以区分新/旧,而不是并发/完整。但在大多数情况下,这已经足够了 在这种情况下,我将进行投票,并使用相关代的
#LastGCInfo
中的before/after信息:
例如,java.lang:type=GarbageCollector,name=PS cleave
是年轻一代,而启用ParallelOld时,java.lang:type=GarbageCollector,name=PS MarkSweep
是老一代
使用CMS,您可以在java.lang:type=GarbageCollector,name=ConcurrentMarkSweep
中看到并发集合和完整集合(但希望永远不会有完整集合:)
这是GC和VM特有的,因此需要一些启发式方法来支持您关心的所有平台
我认为只有飞行记录器事件才有可能进行更细粒度的监控,但我没有这方面的经验。如果您可以访问相关JVM的文件系统,您可以告诉JVM记录有关垃圾收集的信息 对于Oracle Java 8,存在多个标志(从)
-XX:+PrintGC 允许在每个GC打印消息。默认情况下,此选项处于禁用状态 -XX:+PrintGCApplicationncCurrentTime 允许打印自上次暂停(例如GC暂停)以来经过的时间。默认情况下,此选项处于禁用状态 -XX:+PrintGCApplicationStoppedTime 允许打印暂停(例如GC暂停)持续的时间。默认情况下,此选项处于禁用状态 -XX:+printgc邮票 允许在每次GC打印日期戳。默认情况下,此选项处于禁用状态 -XX:+PrintGCDetails 允许在每个GC打印详细消息。默认情况下,此选项处于禁用状态 -XX:+PrintGCTaskTimeStamps 支持打印每个GC工作线程任务的时间戳。默认情况下,此选项处于禁用状态 -XX:+printgc时间戳
允许在每个GC打印时间戳。默认情况下,此选项处于禁用状态。您可以侦听GC通知。请参阅下面的代码 我在这里交叉张贴这个答案,因为它似乎是相关的。基于此,我制作了一个更完整的示例,用于从JVM内部记录GC(从而检测/计算GC)。我希望这能节省一些时间:)
包fi.pelam.gclogutil;
导入java.lang.management.*;
导入java.util.Map;
导入javax.management.openmbean.CompositeData;
导入javax.management.*;
导入com.sun.management.GarbageCollectionNotificationInfo;
导入com.sun.management.GcInfo;
公共类GcLogUtil{
静态公共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
对于(GarbageCollectorMXBean gcMbean:ManagementFactory.getGarbageCollectorMXBeans()){
试一试{
ManagementFactory.getPlatformMBeanServer()。
addNotificationListener(gcMbean.getObjectName(),listener,null,null);
}捕获(例外e){
e、 printStackTrace();
}
}
}
静态私有NotificationListener=新建NotificationListener(){
@凌驾
公共作废处理通知(通知、对象处理){
if(notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE\u COLLECTION\u notification)){
// https://docs.oracle.com/javase/8/docs/jre/api/management/extension/com/sun/management/GarbageCollectionNotificationInfo.html
CompositeData cd=(CompositeData)通知。getUserData();
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);
}
}
GarbageCollectorMXBean fullGcMXBean = null;
List<GarbageCollectorMXBean> gcMxBeanList = ManagementFactory.getGarbageCollectorMXBeans();
for(GarbageCollectorMXBean gcMxBean: gcMxBeanList){
if(gcMxBean.getName().endsWith("MarkSweep")){
fullGcMXBean = gcMxBean;
break;
}
}