jmx-dev [PATCH] JDK-6809322: Missing notifications from javax.management.timer.Timer
Jaroslav Bachorik
jaroslav.bachorik at oracle.com
Mon Oct 15 05:14:58 PDT 2012
On 10/15/2012 01:45 PM, David Holmes wrote:
> On 15/10/2012 8:08 PM, Jaroslav Bachorik wrote:
>> On 10/15/2012 04:19 AM, David Holmes wrote:
>>> I think your changes now go further than needed. The original code uses
>>> a dual synchronization scheme:
>>>
>>> a) it synchronizes most of the Timer methods
>>> b) it also uses a thread-safe Hashtable
>>>
>>> This means that not all of the Timer methods need to be synchronized
>>> because the only thread-safe action needed is the actual access to the
>>> Hashtable in some methods.
>>>
>>> The flaw with the original code was simply that the iteration of the
>>> Hashtable in notifyAlaramClock was not done in a thread-safe manner. I
>>> believe this could be fixed simply by synchronizing on the Hashtable
>>> here:
>>>
>>> 1186 synchronized(timerTable) {
>>>
>>> with no need to change the type of the timerTable, nor the
>>> synchronization on other Timer methods. You could alternatively
>>> synchronize on the Timer itself - as you now do - provided all methods
>>> of the Timer that mutate the Hashtable are themselves synchronized on
>>> the timer.
>>>
>>> What you have is not incorrect though, and may remove unnecessary
>>> synchronization in some cases (but increases the size of critical
>>> sections in others).
>>>
>>> Also here:
>>>
>>> 165 volatile private int counterID = 0;
>>>
>>> there is no need to add volatile as counterID is only accessed within
>>> synchronized methods.
>>
>> Yes, I see your point. I just want to ask - in cases of fixing issues
>> like this the preferred way is to introduce minimal changes even if it
>> means leaving the parts of the code sub-optimal? IMO, having dual
>> synchronization scheme might be considered as sub-optimal as it makes it
>> more difficult to see the author's intentions.
>
> Optimal depends on your evaluation criteria. The original design may
> have been done with performance in mind and a view to minimising
> critical sections. Without knowing what the original design criteria
> was, and unless you are fixing a problem caused by key aspects of that
> design, then minimal changes should be favoured.
>
>> But I am fine with leaving the Hashtable intact and just synchronizing
>> the iteration part correctly - it resolves the issue.
>>
>> The update webrev is available at
>> http://btrace.kenai.com/webrevs/JDK-6809322/webrev.v4
>
> I'm not sure the comment is needed in that form. Hashtable is
> snchronized internally but you need to use external synchronization when
> iterating through it.
Ok, it's gone. http://btrace.kenai.com/webrevs/JDK-6809322/webrev.v5/
>
> David
>
>> Regards,
>>
>> -JB-
>>
>>>
>>> David
>>> -----
>>>
>>> On 12/10/2012 11:14 PM, Jaroslav Bachorik wrote:
>>>> The updated webrev is now at
>>>> http://btrace.kenai.com/webrevs/JDK-6809322/
>>>>
>>>> I am sorry for this chaos with webrev locations but its not that
>>>> easy to
>>>> work efficiently without an OpenJDK username :/
>>>>
>>>> -JB-
>>>>
>>>> On 10/12/2012 09:47 AM, Jaroslav Bachorik wrote:
>>>>> On Fri 12 Oct 2012 04:44:31 AM CEST, David Holmes wrote:
>>>>>> Hi Jaroslav,
>>>>>>
>>>>>>
>>>>>> On 11/10/2012 6:07 PM, Jaroslav Bachorik wrote:
>>>>>>> Dmitry has put the webrev on the public CR -
>>>>>>> http://cr.openjdk.java.net/~dsamersoff/sponsorship/jbachorik/JDK-6809322-v2/
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Thanks!
>>>>>>>
>>>>>>> -JB-
>>>>>>>
>>>>>>> On 10/10/2012 04:17 PM, Jaroslav Bachorik wrote:
>>>>>>>> I am looking for a review and a sponsor.
>>>>>>>>
>>>>>>>> The issue is about some javax.management.timer.Timer notifications
>>>>>>>> not
>>>>>>>> being received by the listeners if the notifications are generated
>>>>>>>> rapidly.
>>>>>>>>
>>>>>>>> The problem is caused by ConcurrentModificationException being
>>>>>>>> thrown -
>>>>>>>> the exception itself is ignored but the dispatcher logic is
>>>>>>>> skipped.
>>>>>>>> Therefore the currently processed notification gets lost.
>>>>>>
>>>>>> Can you point out where exactly in the code the exception is thrown
>>>>>> and caught. I'd like to understand the problem better.
>>>>>
>>>>> The CME is thrown in Timer.notifyAlarmClock() method in this case -
>>>>> but
>>>>> may happen in other places as well.
>>>>>
>>>>> Actually, in some places the access to the timerTable map is
>>>>> synchronized while in others it isn't. While switching the Hashtable
>>>>> for ConcurrentHashMap resolves this particular issue it might be
>>>>> beneficial to correct the partial synchronization instead.
>>>>>
>>>>>>
>>>>>>>>
>>>>>>>> The CME is thrown due to the Timer.timerTable being iterated over
>>>>>>>> while
>>>>>>>> other threads try to remove some of its elements. Fix consists of
>>>>>>>> replacing the Hashtable used for Timer.timerTable by
>>>>>>>> ConcurrentHashMap
>>>>>>>> which handles such situations with grace.
>>>>>>
>>>>>> Be aware that it may also give surprising results as removal is no
>>>>>> longer synchronized at all with processing. So it could now appear
>>>>>> that a notification is processed after a listener has been removed.
>>>>>
>>>>> Indeed, the CME is the symptom of the out-of-order processing - the
>>>>> removal method is synchronized on (Timer.this) while the
>>>>> notifyAlarmClock() method, processing the notifications, runs
>>>>> unsynchronized.
>>>>>
>>>>> Thanks for pointing this out. I will have something to think about.
>>>>>
>>>>> -JB-
>>>>>
>>>>>>
>>>>>> David
>>>>>> -----
>>>>>>
>>>>>>>> The patch webrev is available @
>>>>>>>> https://jbs.oracle.com/bugs/browse/JDK-6809322
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>>
>>>>>>>> -JB-
>>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>>
>>
More information about the serviceability-dev
mailing list