MBean registration happens in a fully synchronized fashion for consistent results

Issue: SPR-11002
This commit is contained in:
Juergen Hoeller 2013-12-11 16:31:26 +01:00
parent 1b4e02b178
commit 8d6d6be39a
1 changed files with 62 additions and 43 deletions

View File

@ -16,7 +16,6 @@
package org.springframework.jmx.support; package org.springframework.jmx.support;
import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceAlreadyExistsException;
@ -113,7 +112,7 @@ public class MBeanRegistrationSupport {
/** /**
* The beans that have been registered by this exporter. * The beans that have been registered by this exporter.
*/ */
private final Set<ObjectName> registeredBeans = Collections.synchronizedSet(new LinkedHashSet<ObjectName>()); private final Set<ObjectName> registeredBeans = new LinkedHashSet<ObjectName>();
/** /**
* The policy used when registering an MBean and finding that it already exists. * The policy used when registering an MBean and finding that it already exists.
@ -188,6 +187,9 @@ public class MBeanRegistrationSupport {
* @throws JMException if the registration failed * @throws JMException if the registration failed
*/ */
protected void doRegister(Object mbean, ObjectName objectName) throws JMException { protected void doRegister(Object mbean, ObjectName objectName) throws JMException {
ObjectName actualObjectName;
synchronized (this.registeredBeans) {
ObjectInstance registeredBean = null; ObjectInstance registeredBean = null;
try { try {
registeredBean = this.server.registerMBean(mbean, objectName); registeredBean = this.server.registerMBean(mbean, objectName);
@ -217,11 +219,13 @@ public class MBeanRegistrationSupport {
} }
// Track registration and notify listeners. // Track registration and notify listeners.
ObjectName actualObjectName = (registeredBean != null ? registeredBean.getObjectName() : null); actualObjectName = (registeredBean != null ? registeredBean.getObjectName() : null);
if (actualObjectName == null) { if (actualObjectName == null) {
actualObjectName = objectName; actualObjectName = objectName;
} }
this.registeredBeans.add(actualObjectName); this.registeredBeans.add(actualObjectName);
}
onRegister(actualObjectName, mbean); onRegister(actualObjectName, mbean);
} }
@ -229,7 +233,11 @@ public class MBeanRegistrationSupport {
* Unregisters all beans that have been registered by an instance of this class. * Unregisters all beans that have been registered by an instance of this class.
*/ */
protected void unregisterBeans() { protected void unregisterBeans() {
for (ObjectName objectName : new LinkedHashSet<ObjectName>(this.registeredBeans)) { Set<ObjectName> snapshot;
synchronized (this.registeredBeans) {
snapshot = new LinkedHashSet<ObjectName>(this.registeredBeans);
}
for (ObjectName objectName : snapshot) {
doUnregister(objectName); doUnregister(objectName);
} }
} }
@ -239,11 +247,15 @@ public class MBeanRegistrationSupport {
* @param objectName the suggested ObjectName for the MBean * @param objectName the suggested ObjectName for the MBean
*/ */
protected void doUnregister(ObjectName objectName) { protected void doUnregister(ObjectName objectName) {
boolean actuallyUnregistered = false;
synchronized (this.registeredBeans) {
if (this.registeredBeans.remove(objectName)) {
try { try {
// MBean might already have been unregistered by an external process. // MBean might already have been unregistered by an external process
if (this.server.isRegistered(objectName)) { if (this.server.isRegistered(objectName)) {
this.server.unregisterMBean(objectName); this.server.unregisterMBean(objectName);
onUnregister(objectName); actuallyUnregistered = true;
} }
else { else {
if (logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
@ -257,15 +269,22 @@ public class MBeanRegistrationSupport {
logger.error("Could not unregister MBean [" + objectName + "]", ex); logger.error("Could not unregister MBean [" + objectName + "]", ex);
} }
} }
this.registeredBeans.remove(objectName); }
}
if (actuallyUnregistered) {
onUnregister(objectName);
}
} }
/** /**
* Return the {@link ObjectName ObjectNames} of all registered beans. * Return the {@link ObjectName ObjectNames} of all registered beans.
*/ */
protected final ObjectName[] getRegisteredObjectNames() { protected final ObjectName[] getRegisteredObjectNames() {
synchronized (this.registeredBeans) {
return this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]); return this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]);
} }
}
/** /**