JDK-6239400 : ArrayNotificationBuffer.createListeners should not be synchronized
  • Type: Bug
  • Component: core-svc
  • Sub-Component: javax.management
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2005-03-11
  • Updated: 2010-07-29
  • Resolved: 2005-04-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6 Other
5.0u6,jdmk5.1_03Fixed 6 b31Fixed jdmk5.1_03Fixed
Description
com.sun.jmx.remote.internal.ArrayNotificationBuffer.createListeners is synchronized.  This method is called from the ArrayNotificationBuffer constructor in order to add a listener to every NotificationBroadcaster MBean that will add all Notifications from that MBean to the ArrayNotificationBuffer.  (This means that the ArrayNotificationBuffer constructor is giving out a reference to "this", which is not very good practice, but tricky to fix.)  While the method is running, a Notification can be sent from one of the MBeans already handled.  This Notification will therefore be added to the ArrayNotificationBuffer, which implies locking it.  The request to do that will block until listeners have been added to every MBean, a potentially slow operation.  We have had a report of a deadlock produced by this situation: an NotificationBroadcaster MBean reacted to an event by asking the MBeanServerDelegate to send a Notification.  The ArrayNotificationBuffer listener on the MBeanServerDelegate blocked waiting for the ArrayNotificationBuffer.  Then when the createListeners thread arrived at this same NotificationBroadcaster, it added addNotificationListener.  The NotificationBroadcaster was holding the lock protecting its listener list while it was sending the Notification (which is a bad idea, see 6239392).

So we had:
Thread 1:
  ArrayNotificationBuffer.createListeners
  lock(ArrayNotificationBuffer)
    |
    v
  BadNotificationBroadcaster.addNotificationListener
  lock(BadNotificationBroadcaster.listenerList)

Thread 2:
  BadNotificationBroadcaster.sendNotification
  lock(BadNotificationBroadcaster.listenerList)
    |
    v
  MBeanServerDelegate.sendNotification
    |
    v
  ArrayNotificationBuffer.bufferListener.handleNotification
  lock(ArrayNotificationBuffer)

The createListeners method is only called from the constructor, so there is no problem with it being called concurrently from more than one place.  It doesn't require exclusive access to anything accessible from other methods, so it doesn't need to be synchronized.
###@###.### 2005-03-11 12:02:30 GMT

Comments
SUGGESTED FIX Remove the synchronized keyword from the createListeners method. ###@###.### 2005-03-11 12:02:30 GMT
11-03-2005

EVALUATION The combination of circumstances leading to deadlock seems pretty unlikely. But it has happened once, so we should prevent it from happening again. ###@###.### 2005-03-11 12:02:30 GMT
11-03-2005