利用JMX的Notifications监听GC
来源:互联网 发布:8848 m3手机备份数据 编辑:程序博客网 时间:2024/06/09 18:36
在Java 7 update 4之前,用java代码监听GC运行情况是不可能的,Java 7 update 4之后,每个垃圾收集器都提供了通知机制,通过监听GarbageCollectorMXBean,可以得到GC完成之后的详细信息。
用法:
Notification notif; // receive the notification emitted by a GarbageCollectorMXBean and set to notif ... String notifType = notif.getType(); if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { // retrieve the garbage collection notification information CompositeData cd = (CompositeData) notif.getUserData(); GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd); .... }
在GarbageCollectionNotificationInfo中,能获得大多数GC日志里面的内存:
GC详细信息:
内存使用情况:
initrepresents the initial amount of memory (in bytes) that the Java virtual machine requests from the operating system for memory management during startup. The Java virtual machine may request additional memory from the operating system and may also release memory to the system over time. The value of init may be undefined.usedrepresents the amount of memory currently used (in bytes).committedrepresents the amount of memory (in bytes) that is guaranteed to be available for use by the Java virtual machine. The amount of committed memory may change over time (increase or decrease). The Java virtual machine may release memory to the system and committed could be less than init. committed will always be greater than or equal to used.maxrepresents the maximum amount of memory (in bytes) that can be used for memory management. Its value may be undefined. The maximum amount of memory may change over time if defined. The amount of used and committed memory will always be less than or equal to max if max is defined. A memory allocation may fail if it attempts to increase the used memory such that used > committed even if used less equal max would still be true (for example, when the system is low on virtual memory).Below is a picture showing an example of a memory pool:
+----------------------------------------------+ +//////////////// | + +//////////////// | + +----------------------------------------------+ |--------| init |---------------| used |---------------------------| committed |----------------------------------------------|
目前的监听机制只能得到GC完成之后
的数据,其它环节的GC情况无法观察到。
并且gc的详细信息中的耗时也没有细分停顿时间
和并发时间
,相信这个数据更为重要。
实例:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
/*** gc monitoring only on jdk7 or later** @author lichengwu* @version 1.0* @created 2013-09-14 10:44 PM*/public class GCMonitoring {private static final long JVM_START_TIME = ManagementFactory.getRuntimeMXBean().getStartTime();private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");private static final long ONE_BYTE = 1024;public static void init() {//get all GarbageCollectorMXBeansList<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();//register every GarbageCollectorMXBeanfor (GarbageCollectorMXBean gcBean : gcBeans) {System.out.println("register " + gcBean.getName() + " for " + Arrays.deepToString(gcBean.getMemoryPoolNames()));NotificationEmitter emitter = (NotificationEmitter) gcBean;//new listenerNotificationListener listener = new NotificationListener() {//record total gc time spendlong totalGcTimeSpend = 0;@Overridepublic void handleNotification(Notification notification, Object handback) {HandBack handBack = (HandBack) handback;//get gc infoGarbageCollectionNotificationInfo info =GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());//outputString gcType = info.getGcAction();if (gcType.length() > 7) {gcType = gcType.substring(7);}//get a glance of gcStringBuilder gcGlance = new StringBuilder();gcGlance.append(gcType).append(": - ").append(info.getGcInfo().getId());gcGlance.append(" (").append(info.getGcCause()).append(") ");gcGlance.append("start: ").append(dateFormat.format(new Date(JVM_START_TIME + info.getGcInfo().getStartTime())));gcGlance.append(", end: ").append(dateFormat.format(new Date(JVM_START_TIME + info.getGcInfo().getEndTime())));System.out.println(gcGlance.toString());//memory infoMap<String, MemoryUsage> beforeUsageMap = info.getGcInfo().getMemoryUsageBeforeGc();Map<String, MemoryUsage> afterUsageMap = info.getGcInfo().getMemoryUsageAfterGc();for (Map.Entry<String, MemoryUsage> entry : afterUsageMap.entrySet()) {String name = entry.getKey();MemoryUsage afterUsage = entry.getValue();MemoryUsage beforeUsage = beforeUsageMap.get(name);StringBuilder usage = new StringBuilder();usage.append("\t[").append(name).append("] ");usage.append("init:").append(afterUsage.getInit() / ONE_BYTE).append("K; ");usage.append("used:").append(handBack.handUsage(beforeUsage.getUsed(), afterUsage.getUsed(), beforeUsage.getMax())).append("; ");usage.append("committed: ").append(handBack.handUsage(beforeUsage.getCommitted(), afterUsage.getCommitted(),beforeUsage.getMax()));System.out.println(usage.toString());}totalGcTimeSpend += info.getGcInfo().getDuration();//summarylong percent =(info.getGcInfo().getEndTime() - totalGcTimeSpend) * 1000L / info.getGcInfo().getEndTime();StringBuilder summary = new StringBuilder();summary.append("duration:").append(info.getGcInfo().getDuration()).append("ms");summary.append(", throughput:").append((percent / 10)).append(".").append(percent % 10).append('%');System.out.println(summary.toString());System.out.println();}};//add the listeneremitter.addNotificationListener(listener, new NotificationFilter() {private static final long serialVersionUID = 3763793138186359389L;@Overridepublic boolean isNotificationEnabled(Notification notification) {//filter GC notificationreturn notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION);}}, HandBack.getInstance());}}private static class HandBack {private HandBack() {}private static HandBack instance = new HandBack();public static HandBack getInstance() {return instance;}public String handUsage(long before, long after, long max) {StringBuilder usage = new StringBuilder();if (max == -1) {usage.append("").append(before / ONE_BYTE).append("K -> ").append(after / ONE_BYTE).append("K)");return usage.toString();}long beforePercent = ((before * 1000L) / max);long afterPercent = ((after * 1000L) / max);usage.append(beforePercent / 10).append('.').append(beforePercent % 10).append("%(").append(before / ONE_BYTE).append("K) -> ").append(afterPercent / 10).append('.').append(afterPercent % 10).append("%(").append(after / ONE_BYTE).append("K)");return usage.toString();}}}
123456789101112131415161718192021222324252627282930313233343536
register G1 Young Generation for [G1 Eden Space, G1 Survivor Space]register G1 Old Generation for [G1 Eden Space, G1 Survivor Space, G1 Old Gen, G1 Perm Gen]major GC: - 1 (System.gc()) start: 2013-09-15 09:38:35.193, end: 2013-09-15 09:38:59.283[G1 Eden Space] init:26624K; used:3072K -> 4096K); committed: 26624K -> 26624K)[G1 Old Gen] init:97280K; used:0.0%(0K) -> 0.0%(0K); committed: 4.9%(97280K) -> 4.9%(97280K)[Code Cache] init:2496K; used:0.8%(433K) -> 0.8%(433K); committed: 5.0%(2496K) -> 5.0%(2496K)[G1 Perm Gen] init:20480K; used:5.9%(5012K) -> 5.9%(5012K); committed: 24.3%(20480K) -> 24.3%(20480K)[G1 Survivor Space] init:0K; used:0K -> 0K); committed: 0K -> 0K)duration:24090ms, throughput:87.3%minor GC: - 1 (G1 Humongous Allocation) start: 2013-09-15 09:38:59.618, end: 2013-09-15 09:39:00.870[G1 Eden Space] init:26624K; used:0K -> 1024K); committed: 4096K -> 4096K)[G1 Old Gen] init:97280K; used:0.1%(1990K) -> 0.1%(1990K); committed: 0.1%(3072K) -> 0.1%(3072K)[Code Cache] init:2496K; used:0.8%(433K) -> 0.8%(433K); committed: 5.0%(2496K) -> 5.0%(2496K)[G1 Perm Gen] init:20480K; used:5.9%(5017K) -> 5.9%(5017K); committed: 24.3%(20480K) -> 24.3%(20480K)[G1 Survivor Space] init:0K; used:0K -> 0K); committed: 0K -> 0K)duration:1252ms, throughput:99.3%minor GC: - 2 (G1 Humongous Allocation) start: 2013-09-15 09:39:21.662, end: 2013-09-15 09:39:23.649[G1 Eden Space] init:26624K; used:1024K -> 1024K); committed: 2048K -> 2048K)[G1 Old Gen] init:97280K; used:1.8%(35814K) -> 1.8%(35814K); committed: 3.7%(73728K) -> 3.7%(73728K)[Code Cache] init:2496K; used:0.8%(437K) -> 0.8%(437K); committed: 5.0%(2496K) -> 5.0%(2496K)[G1 Perm Gen] init:20480K; used:6.5%(5487K) -> 6.5%(5487K); committed: 24.3%(20480K) -> 24.3%(20480K)[G1 Survivor Space] init:0K; used:1024K -> 1024K); committed: 1024K -> 1024K)duration:1987ms, throughput:98.4%minor GC: - 3 (G1 Humongous Allocation) start: 2013-09-15 09:39:42.826, end: 2013-09-15 09:39:46.322[G1 Eden Space] init:26624K; used:1024K -> 1024K); committed: 45056K -> 45056K)[G1 Old Gen] init:97280K; used:1.8%(35910K) -> 1.8%(35910K); committed: 5.5%(109568K) -> 5.5%(109568K)[Code Cache] init:2496K; used:0.8%(440K) -> 0.8%(440K); committed: 5.0%(2496K) -> 5.0%(2496K)[G1 Perm Gen] init:20480K; used:6.5%(5533K) -> 6.5%(5533K); committed: 24.3%(20480K) -> 24.3%(20480K)[G1 Survivor Space] init:0K; used:1024K -> 1024K); committed: 1024K -> 1024K)duration:3496ms, throughput:97.1%Process finished with exit code 0
- 利用JMX的Notifications监听GC
- JMX学习笔记(四):Notifications
- 利用JMX 监控 tomcat
- 利用JMX监控tomcat
- 利用JMX监控ActiveMQ
- 使用JMX来获取CPU利用率和GC 所占用的CPU利用率
- 利用JMX统计远程JAVA进程的CPU和Memory
- 利用JMX统计远程JAVA进程的CPU和Memory
- 利用JMX统计远程JAVA进程的CPU和Memory
- WP7的Push Notifications
- 强大的 ActiveSupport::Notifications
- 通过Java/JMX得到full GC次数
- Notifications
- notifications
- Notifications
- Notifications
- Notifications
- Notifications
- WOW------像猎人一样的活着
- Oracle 时间戳生成语句(秒级+毫秒级)
- HTML5 Quick Start Web Application
- 得到下拉框的值 赋给另外一个下拉框
- 基于MysqlConnector/C++的数据库连接池的实现
- 利用JMX的Notifications监听GC
- ssh-keygen的使用方法(无密码访问)
- 互联网人才如何做好职业规划
- htmlcomplete#CompleteTags 的 bug
- hdoj1022 Train Problem I ( stack )
- 《程序员》 -- 技术团队新官上任之中层篇
- linux MySQL-server-5.5.34-1.el6.i686.rpm安装
- Stripes视图框架简介
- Weblogic异常