MemoryMXBean NotificationListener占用堆空间

时间:2015-12-17 17:33:44

标签: java jmx

JMX通知监听器会耗尽多少内存?

我有一个带有小Max Heap的Java 7应用程序。

我使用单个MemoryMXBean通知侦听器监视它,并且大部分Heap都用完了。内存分析器报告:

  

" com.sun.jmx.remote.internal.ArrayNotificationBuffer"的一个实例   由"系统类加载器加载"占用16,810,416(52.18%)个字节。   该实例引用   sun.management.NotificationEmitterSupport $ ListenerInfo @ 0xeda6d9e0,   由"系统类加载器"加载。记忆累积在一个   " java.lang.Object []"的实例由"系统类加载器加载"。

我的代码

final MemoryMXBean mbean = ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection, MEMORY_MXBEAN_NAME, MemoryMXBean.class);
NotificationEmitter emitter = (NotificationEmitter) mbean;
emitter.addNotificationListener(new NotificationListener() {
    @Override
    public void handleNotification(Notification notification, Object handback) {

        if (notification.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
            LOG.info("Memory threshold exceeded !!!");
        }

        if (notification.getType().equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
            LOG.error("Memory Collection threshold exceeded !!!");
        }

    }
}, null, null);

1 个答案:

答案 0 :(得分:2)

当您在代码中创建内部类(如NotifcationListener)时,该类将获取一个隐藏字段,该字段包含对创建实例的对象的引用。

您可以通过声明内部类静态来修复内存泄漏,

static class LogListener implements NotifciationListener {
  @Override
  public void handleNotification(Notification notification, Object handback) {
    LOG.info("Notification!"); 
  }   
}

然后创建一个像这样的实例

 MemoryMXBean mbean = ManagementFactory.newPlatformMXBeanProxy(mBeanServerConnection,
    MEMORY_MXBEAN_NAME, MemoryMXBean.class);
 NotificationEmitter emitter = (NotificationEmitter) mbean;
 emitter.addNotificationListener(new LogListener());