Reputation: 18144
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
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