java 程序如何发现自己经历了长时间的 GC 暂停?
How can a java program find itself has experienced a long GC pause?
我正在编写一个可以有长时间 GC 暂停的程序,但是 SLA 说我不应该有太多暂停。如果它发现任何东西,它需要报告。
如何让它监控自己?我不想解析 GC 日志。
JMX暴露了LastGcInfo,但是不知道什么时候查询
在用户代码中让应用程序处理 GC 相关监控并不是一个好主意space。有时应用程序处于状态(接近 OOM),它将无法执行用户代码并且监控可能会继续中断。
如果您无论如何都想这样做(风险自负),您可以像这样将侦听器挂接到 GC 并检查 GC 持续时间。
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
NotificationEmitter emitter = (NotificationEmitter) gcBean;
emitter.addNotificationListener(new CustomNotificationListener(), null, null);
}
和
class CustomNotificationListener implements javax.management.NotificationListener {
@Override
public void handleNotification(Notification notification, Object handback) {
// hook your logic here.
String notifType = notification.getType();
if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
// retrieve the garbage collection notification information
CompositeData cd = (CompositeData) notification.getUserData();
GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd);
System.out.println(info.getGcInfo().getDuration());
}
}
}
@Jigar 的回答显示了如何监控 GC 事件。但是,我认为这不会允许一个线程测量它……或另一个线程……暂停了多长时间。
事实上,我怀疑没有办法衡量它。
事实上,我认为也没有办法衡量其他类型的停顿;例如
- 因等待 I/O
而暂停
- 由于同步而暂停,或
- 由于 OS 受控时间片而暂停。
我认为你想做的事情不可行,更不明智。
查看您的要求:
I am writing a program that can have long GC pauses, however the SLA said I shouldn't have too many of them. And it needs to report if it finds any.
SLA 可能没有在 GC 暂停方面提出 1。它将根据响应时间来表达。这有很大的不同。响应时间比 GC 暂停更容易衡量。
SLA 不太可能说您必须测量应用程序本身的响应时间(或其他)。所以在外面量一下:
- 在单独的实时监控系统中分析应用程序/网络容器日志事件;例如Nagios、CheckMk 等。
- 事后扫描应用程序/Web 容器日志文件。
- 将数据包或流量监控连接到记录响应时间的东西。
如果您决定忽略 2),请考虑您在 Java 到 "self monitor" 应用程序中放入的任何额外基础设施都会使其变得更加复杂,并且(除非您小心)添加GC 负载,使 GC 暂停 更频繁。
简而言之:由于您可能不需要这样做,我考虑过的建议是不要尝试检测应用程序本身的 GC 暂停。
1 - 如果是,那么有人在编写/协商 SLA 时犯了错误!
在直接跳转到付费 Java APM 应用程序或临时实施之前,请先查看 Glowroot。
它是免费和开源的,让您可以监控一系列指标,包括 GC 收集时间、堆使用情况。也可以向您和您的合作者发送带有警报的电子邮件。
很少有人会注意到 overhead。我已经将它用于预算很少或根本没有预算的应用程序一段时间了。
试一试(这里有demo),然后选择更适合您需求的APM。
我正在编写一个可以有长时间 GC 暂停的程序,但是 SLA 说我不应该有太多暂停。如果它发现任何东西,它需要报告。
如何让它监控自己?我不想解析 GC 日志。
JMX暴露了LastGcInfo,但是不知道什么时候查询
在用户代码中让应用程序处理 GC 相关监控并不是一个好主意space。有时应用程序处于状态(接近 OOM),它将无法执行用户代码并且监控可能会继续中断。
如果您无论如何都想这样做(风险自负),您可以像这样将侦听器挂接到 GC 并检查 GC 持续时间。
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
NotificationEmitter emitter = (NotificationEmitter) gcBean;
emitter.addNotificationListener(new CustomNotificationListener(), null, null);
}
和
class CustomNotificationListener implements javax.management.NotificationListener {
@Override
public void handleNotification(Notification notification, Object handback) {
// hook your logic here.
String notifType = notification.getType();
if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
// retrieve the garbage collection notification information
CompositeData cd = (CompositeData) notification.getUserData();
GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd);
System.out.println(info.getGcInfo().getDuration());
}
}
}
@Jigar 的回答显示了如何监控 GC 事件。但是,我认为这不会允许一个线程测量它……或另一个线程……暂停了多长时间。
事实上,我怀疑没有办法衡量它。
事实上,我认为也没有办法衡量其他类型的停顿;例如
- 因等待 I/O 而暂停
- 由于同步而暂停,或
- 由于 OS 受控时间片而暂停。
我认为你想做的事情不可行,更不明智。
查看您的要求:
I am writing a program that can have long GC pauses, however the SLA said I shouldn't have too many of them. And it needs to report if it finds any.
SLA 可能没有在 GC 暂停方面提出 1。它将根据响应时间来表达。这有很大的不同。响应时间比 GC 暂停更容易衡量。
SLA 不太可能说您必须测量应用程序本身的响应时间(或其他)。所以在外面量一下:
- 在单独的实时监控系统中分析应用程序/网络容器日志事件;例如Nagios、CheckMk 等。
- 事后扫描应用程序/Web 容器日志文件。
- 将数据包或流量监控连接到记录响应时间的东西。
如果您决定忽略 2),请考虑您在 Java 到 "self monitor" 应用程序中放入的任何额外基础设施都会使其变得更加复杂,并且(除非您小心)添加GC 负载,使 GC 暂停 更频繁。
简而言之:由于您可能不需要这样做,我考虑过的建议是不要尝试检测应用程序本身的 GC 暂停。
1 - 如果是,那么有人在编写/协商 SLA 时犯了错误!
在直接跳转到付费 Java APM 应用程序或临时实施之前,请先查看 Glowroot。
它是免费和开源的,让您可以监控一系列指标,包括 GC 收集时间、堆使用情况。也可以向您和您的合作者发送带有警报的电子邮件。
很少有人会注意到 overhead。我已经将它用于预算很少或根本没有预算的应用程序一段时间了。
试一试(这里有demo),然后选择更适合您需求的APM。