通过配置JMX监听GC基本信息
利用JMX的Notifications监听GC
JMX
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,
实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。主要用于对JAVA应用程序和JVM进行监控和管理。
包java.lang.management javax.management
JMX分为三层
基础层MBean,分为标准MBean、动态MBean、MXBean等
代理层(适配层)提供对MBean的管理
远程代理层,可以通过http、snmp、rmi等不同的协议去管理具体的mbean资源
可使用内置的mxbean和自定义mxbean 暴露系统状态
类型 描述
standard MBean 一个标准的MBean由一个MBean接口(该MBean接口列出了所有被暴露的属性和操作对应的方法)
和一个class(这 个class实现了这个MBean接口并提供被监测资源的功能)组成(接口和class必须放在同一个包下,不然会出错)。
它的命名也必须遵循一定的规范,例如我们的MBean为Test,则接口必须为TestMBean。标准MBean只能操作基本数据类型
dynamic MBean 必须实现javax.management.DynamicMBean接口,所有的属性,方法都在运行时定义
model MBean 与标准和动态MBean相比,你可以不用写MBean类,只需使用javax.management.modelmbean.RequiredModelMBean即可。
RequiredModelMBean实现了ModelMBean接口,而ModelMBean扩展了DynamicMBean接口,因此与DynamicMBean相似,
Model MBean的管理资源也是在运行时定义的。与DynamicMBean不同的是,DynamicMBean管理的资源一般定义
在DynamicMBean中(运行时才决定管理那些资源),而model MBean管理的资源并不在MBean中,而是在外部(通常是一个类),
只有在运行时,才通过set方法将其加入到model MBean中。后面的例子会有详细介绍
Notificationn
JMX API定义了一种机制,使得MBeans能够生成通知Notificationn,比如通知一个状态改变、一个检测到的事件或者问题,系统状态,gc事件。通知的作用是主动通知远程客户端。例如程序出现异常,CPU使用率过高,出现了死锁等。这时程序能事件触发主动发送给远程客户端,将这些问题记录下来,或者执行一些其他的报警操作。
javax.management.Notification
一个MBean生成通知必须实现接口 NotificationEmitter 或者扩展 NotificationBroadcasterSupport
public class NotificationBroadcasterSupport implements NotificationEmitter {
...
public MBeanNotificationInfo[] getNotificationInfo(){...}
public void sendNotification(Notification notification){...}
...
}
Notificationn监听器必须实现NotificationListener接口
代码
获取mxbean
for (GarbageCollectorMXBean mbean:ManagementFactory.getGarbageCollectorMXBeans()) {
if (!(mbean instanceof NotificationEmitter)) {
continue;//假如不支持监听...
}
final NotificationEmitter emitter = (NotificationEmitter) mbean;//添加监听
// final NotificationListener listener = getNewListener(mbean);
final NotificationListener listener = new GarbageNotificationListener();
emitter.addNotificationListener(listener,null,null);
}
监听器 需要实现NotificationListener
static class GarbageNotificationListener implements NotificationListener {
@Override
public void handleNotification(Notification notification, Object handback) {
String notifType = notification.getType();
if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
CompositeData cd = (CompositeData) notification.getUserData();
GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd);
GcInfo gcInfo = info.getGcInfo();
HashMap<String, Object> map = new HashMap<>();
map.put("duration", gcInfo.getDuration());
map.put("id", gcInfo.getId());
map.put("UsageAfterGc", gcInfo.getMemoryUsageAfterGc());
map.put("UsageBeforeGc", gcInfo.getMemoryUsageBeforeGc());
map.put("GcAction", info.getGcAction());
map.put("GcCause", info.getGcCause());
map.put("GcName", info.getGcName());
System.out.println(map);
}
}
}
打印结果
{duration=3, GcAction=end of minor GC, GcCause=G1 Evacuation Pause, GcName=G1 Young Generation, id=8}
{duration=4, GcAction=end of minor GC, GcCause=G1 Evacuation Pause, GcName=G1 Young Generation, id=9}
{duration=1, GcAction=end of minor GC, GcCause=G1 Humongous Allocation, GcName=G1 Young Generation, id=10}
{duration=4, GcAction=end of minor GC, GcCause=G1 Evacuation Pause, GcName=G1 Young Generation, id=11}
{duration=6, GcAction=end of minor GC, GcCause=G1 Evacuation Pause, GcName=G1 Young Generation, id=12}
{duration=15, GcAction=end of minor GC, GcCause=G1 Humongous Allocation, GcName=G1 Young Generation, id=13}