Skip to content

Commit 8d6d6be

Browse files
committed
MBean registration happens in a fully synchronized fashion for consistent results
Issue: SPR-11002
1 parent 1b4e02b commit 8d6d6be

File tree

1 file changed

+62
-43
lines changed

1 file changed

+62
-43
lines changed

spring-context/src/main/java/org/springframework/jmx/support/MBeanRegistrationSupport.java

+62-43
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.jmx.support;
1818

19-
import java.util.Collections;
2019
import java.util.LinkedHashSet;
2120
import java.util.Set;
2221
import javax.management.InstanceAlreadyExistsException;
@@ -113,7 +112,7 @@ public class MBeanRegistrationSupport {
113112
/**
114113
* The beans that have been registered by this exporter.
115114
*/
116-
private final Set<ObjectName> registeredBeans = Collections.synchronizedSet(new LinkedHashSet<ObjectName>());
115+
private final Set<ObjectName> registeredBeans = new LinkedHashSet<ObjectName>();
117116

118117
/**
119118
* The policy used when registering an MBean and finding that it already exists.
@@ -188,48 +187,57 @@ public void setRegistrationPolicy(RegistrationPolicy registrationPolicy) {
188187
* @throws JMException if the registration failed
189188
*/
190189
protected void doRegister(Object mbean, ObjectName objectName) throws JMException {
191-
ObjectInstance registeredBean = null;
192-
try {
193-
registeredBean = this.server.registerMBean(mbean, objectName);
194-
}
195-
catch (InstanceAlreadyExistsException ex) {
196-
if (this.registrationPolicy == RegistrationPolicy.IGNORE_EXISTING) {
197-
if (logger.isDebugEnabled()) {
198-
logger.debug("Ignoring existing MBean at [" + objectName + "]");
199-
}
190+
ObjectName actualObjectName;
191+
192+
synchronized (this.registeredBeans) {
193+
ObjectInstance registeredBean = null;
194+
try {
195+
registeredBean = this.server.registerMBean(mbean, objectName);
200196
}
201-
else if (this.registrationPolicy == RegistrationPolicy.REPLACE_EXISTING) {
202-
try {
197+
catch (InstanceAlreadyExistsException ex) {
198+
if (this.registrationPolicy == RegistrationPolicy.IGNORE_EXISTING) {
203199
if (logger.isDebugEnabled()) {
204-
logger.debug("Replacing existing MBean at [" + objectName + "]");
200+
logger.debug("Ignoring existing MBean at [" + objectName + "]");
201+
}
202+
}
203+
else if (this.registrationPolicy == RegistrationPolicy.REPLACE_EXISTING) {
204+
try {
205+
if (logger.isDebugEnabled()) {
206+
logger.debug("Replacing existing MBean at [" + objectName + "]");
207+
}
208+
this.server.unregisterMBean(objectName);
209+
registeredBean = this.server.registerMBean(mbean, objectName);
210+
}
211+
catch (InstanceNotFoundException ex2) {
212+
logger.error("Unable to replace existing MBean at [" + objectName + "]", ex2);
213+
throw ex;
205214
}
206-
this.server.unregisterMBean(objectName);
207-
registeredBean = this.server.registerMBean(mbean, objectName);
208215
}
209-
catch (InstanceNotFoundException ex2) {
210-
logger.error("Unable to replace existing MBean at [" + objectName + "]", ex2);
216+
else {
211217
throw ex;
212218
}
213219
}
214-
else {
215-
throw ex;
220+
221+
// Track registration and notify listeners.
222+
actualObjectName = (registeredBean != null ? registeredBean.getObjectName() : null);
223+
if (actualObjectName == null) {
224+
actualObjectName = objectName;
216225
}
226+
this.registeredBeans.add(actualObjectName);
217227
}
218228

219-
// Track registration and notify listeners.
220-
ObjectName actualObjectName = (registeredBean != null ? registeredBean.getObjectName() : null);
221-
if (actualObjectName == null) {
222-
actualObjectName = objectName;
223-
}
224-
this.registeredBeans.add(actualObjectName);
225229
onRegister(actualObjectName, mbean);
226230
}
227231

228232
/**
229233
* Unregisters all beans that have been registered by an instance of this class.
230234
*/
231235
protected void unregisterBeans() {
232-
for (ObjectName objectName : new LinkedHashSet<ObjectName>(this.registeredBeans)) {
236+
Set<ObjectName> snapshot;
237+
synchronized (this.registeredBeans) {
238+
snapshot = new LinkedHashSet<ObjectName>(this.registeredBeans);
239+
}
240+
for (ObjectName objectName : snapshot) {
233241
doUnregister(objectName);
234242
}
235243
}
@@ -239,32 +247,43 @@ protected void unregisterBeans() {
239247
* @param objectName the suggested ObjectName for the MBean
240248
*/
241249
protected void doUnregister(ObjectName objectName) {
242-
try {
243-
// MBean might already have been unregistered by an external process.
244-
if (this.server.isRegistered(objectName)) {
245-
this.server.unregisterMBean(objectName);
246-
onUnregister(objectName);
247-
}
248-
else {
249-
if (logger.isWarnEnabled()) {
250-
logger.warn("Could not unregister MBean [" + objectName + "] as said MBean " +
251-
"is not registered (perhaps already unregistered by an external process)");
250+
boolean actuallyUnregistered = false;
251+
252+
synchronized (this.registeredBeans) {
253+
if (this.registeredBeans.remove(objectName)) {
254+
try {
255+
// MBean might already have been unregistered by an external process
256+
if (this.server.isRegistered(objectName)) {
257+
this.server.unregisterMBean(objectName);
258+
actuallyUnregistered = true;
259+
}
260+
else {
261+
if (logger.isWarnEnabled()) {
262+
logger.warn("Could not unregister MBean [" + objectName + "] as said MBean " +
263+
"is not registered (perhaps already unregistered by an external process)");
264+
}
265+
}
266+
}
267+
catch (JMException ex) {
268+
if (logger.isErrorEnabled()) {
269+
logger.error("Could not unregister MBean [" + objectName + "]", ex);
270+
}
252271
}
253272
}
254273
}
255-
catch (JMException ex) {
256-
if (logger.isErrorEnabled()) {
257-
logger.error("Could not unregister MBean [" + objectName + "]", ex);
258-
}
274+
275+
if (actuallyUnregistered) {
276+
onUnregister(objectName);
259277
}
260-
this.registeredBeans.remove(objectName);
261278
}
262279

263280
/**
264281
* Return the {@link ObjectName ObjectNames} of all registered beans.
265282
*/
266283
protected final ObjectName[] getRegisteredObjectNames() {
267-
return this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]);
284+
synchronized (this.registeredBeans) {
285+
return this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]);
286+
}
268287
}
269288

270289

0 commit comments

Comments
 (0)