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
|