堆 space 被 MemoryMXBean NotificationListener 占用

Heap space being taken up by MemoryMXBean NotificationListener

JMX 通知侦听器将使用多少内存?

我有一个 Java 7 的应用程序,它的最大堆很小。

我用一个 MemoryMXBean 通知侦听器监视它,但大部分堆都用完了。内存分析器报告:

One instance of "com.sun.jmx.remote.internal.ArrayNotificationBuffer" loaded by "system class loader" occupies 16,810,416 (52.18%) bytes. The instance is referenced by sun.management.NotificationEmitterSupport$ListenerInfo @ 0xeda6d9e0 , loaded by "system class loader". The memory is accumulated in one instance of "java.lang.Object[]" loaded by "system class loader".

我的代码

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);

当您创建内部 class 时,就像您代码中的 NotifcationListener 一样,class 会获得一个隐藏字段,该字段包含对创建实例的对象的引用。

您可以通过声明内部 class 静态

来修复内存泄漏
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());