JDK-6222826 : JMX API creates one thread per Monitor
  • Type: Enhancement
  • Component: core-svc
  • Sub-Component: javax.management
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2005-01-28
  • Updated: 2017-05-16
  • Resolved: 2005-04-30
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.
JDK 6
6 b35Fixed
Description
Although a single Monitor can sample any number of MBeans, it can only do so if the attribute to be sampled and the threshold (etc) to apply are the same for all of them.  So for example if you have 1000 DiskMBean objects each with a Used attribute, and you want to apply a different threshold to each one, then you need 1000 Monitors.  Today, if you create 1000 Monitors, you get 1000 threads that spend nearly all of their time idle, waking up periodically to monitor some attributes.

A simple but inadequate way to address this problem is simply to say that all Monitors share the same thread.  The drawback is that if any Monitor is sampling a slow attribute (say a remote proxy), then all Monitors get held up.

This could be addressed with API changes or just implementation changes.

An API change could allow users to say explicitly that they want several Monitors to share the same thread, either via a ScheduledExecutorService parameter in the constructor, or via some sort of capability (e.g. java.util.UUID) where two Monitors created with the same capability share the same thread.

Alternatively, the implementation could be changed to be smarter about thread usage.  You do not need to have more than one thread waiting for a scheduled wakeup.  You only need to have one thread that is waiting for the earliest such wakeup, plus logic to (a) give it an earlier wakeup time and (b) start or reuse a second waiting thread before calling getAttribute if there is at least one other waiting Monitor.  In the example above, this means that you can still have 1000 threads, but only if 999 getAttribute calls run simultaneously, presumably because some of them are slow.  In practice, we could provide an upper bound on the number of threads created, default something like 10, and settable by a system property.

The main potential problem here is that if all 1000 Monitors have the same fixed-rate schedule, naive logic is still likely to try to create a large number of threads.  The schedule-waiting thread wakes up for Monitor 1, sees that there is no other schedule-waiting thread, so creates one before calling getAttribute.  The second thread is immediately scheduled for Monitor 2, again sees that there is no other schedule-waiting thread, so creates one before calling getAttribute.  Etc.  Threads will be continually created until the getAttribute calls start returning, so if those calls are even a bit slow you can end up with a storm of new threads.  This might require some tricky logic to add a bit of slack into the scheduling.
###@###.### 2005-1-28 11:30:46 GMT

Comments
EVALUATION Needs investigation of possible approaches. Should be fixable in Mustang. ###@###.### 2005-1-28 11:31:43 GMT The chosen solution was to have a thread pool that is shared by all Monitors. The default size of this pool is 10, so at most 10 threads will be created to handle the sampling for all Monitors. A system property jmx.x.monitor.maximum.pool.size allows a different maximum size to be specified. Threads are created on demand, and destroyed after 60 seconds idle time, so the number of sampling threads will rarely be as big as the maximum size. ###@###.### 2005-05-11 13:21:51 GMT
28-01-2005