DarVar
DarVar

Reputation: 18144

Heap space being taken up by MemoryMXBean NotificationListener

How much memory will JMX Notification Listeners use up?

I have a Java 7 application with a small Max Heap.

I was monitoring it with a single MemoryMXBean notification listener and most of the Heap got used up. Memory Analyser report:

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".

My code

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

Upvotes: 0

Views: 953

Answers (1)

Kire Haglin
Kire Haglin

Reputation: 7079

When you create an inner class, like NotifcationListener in you code, the class gets a hidden field that holds a reference to the object in which the instance was created.

You can fix the memory leak by declaring your inner class static,

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

and then create an instance like this

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

Upvotes: 2

Related Questions