<AWT Dev> <Swing Dev> Review request #4: 6852592 (invalidate() must be smarter) - approved

Anthony Petrov Anthony.Petrov at Sun.COM
Wed Oct 7 07:01:32 PDT 2009


Hi Alex,

On 10/07/2009 05:36 PM, Alexander Potochkin wrote:
>>> Container.descendUnconditionallyWhenValidating looks fishy indeed,
>>> it's better to get rig of it indeed
>>
>> Could you elaborate please?
> 
> Sure
> 
> By the way, I meant "the extra if statements containing 
> Container.descendUnconditionallyWhenValidating look fishy"
> 
> now it should be a bit more clear :-)
> 
> I guess the following thoughts were already expressed by Artem, anyway:
> 
> first of all it is a sort of infamous Double-checked locking antipattern
> http://en.wikipedia.org/wiki/Double-checked_locking
> 
> There are enough serious reasons why not to use it,
> I have read them in a "Java Concurrency" book
> which is alway on my table

That's really surprising to hear from a developer of a single-threaded 
GUI-toolkit! We, AWT people, should have this book instead! ;)

Now back to serious matters, at first I thought you were talking about 
the presence of the descendUnconditionallyWhenValidating variable 
itself, that's why I asked for elaboration. Now I see that basically 
you're speaking about the double-checked locking issue only. Thanks for 
clarifying that.

Indeed, Artem noticed this anti-pattern long-long time ago. Even before 
the new variable is introduced, the idiom involving the bare isValid() 
check has existed in our code for ages. And I agree that we need to get 
rid of that idiom.

However, the current fix for 6852592 does not seem to make things worse: 
it just adds one more check that is basically equal (in possible 
side-effects) to the existing check for isValid(). On the other hand, 
making that change may theoretically bring some regressions if some code 
relies on that behavior. That's why I decided to separate the issues. 
Now we have the following CR:

http://bugs.sun.com/view_bug.do?bug_id=6887249

The fix is actually in progress, and apparently going to hit the 
repository prior to the fix for 6852592 (due to a bit lagging 
specification changes approval process). So I don't have any concern 
regarding the issue in terms of the fix that we're currently reviewing: 
at least the regression testing indicates nothing extremely terrible. I 
hope this explanation calms down your worries. If not, please speak up.

--
best regards,
Anthony

> 
> Moreover your variant is even more risky:
> any field that is going to be accessed via different threads
> must always be used under the lock,
> otherwise it is possible that one thread
> will see the field in an invalid state
> 
> However in your fix the descendUnconditionallyWhenValidating  field
> is mutated under the treeLock and then accessed in the validate() method
> outside the synchronization block which is unsafe
> 
> The following comment: /* Avoid grabbing lock unless really necessary.*/
> 
> is obsolete, the modern JVM do a great job to optimize synchronization
> so there is no need to invent tricky patterns to avoid synchronization
> 
> I see two options here:
> 
> 1) Refactor Container.validate to alway get the treeLock and
> do everything inside it. This is the most preferable choice.
> 
> 2) Define descendUnconditionallyWhenValidating as volatile,
> this is better than nothing but less safe than #1
> 
> Thanks
> alexp
> 
>>
>> -- 
>> best regards,
>> Anthony
>>
>>>> On 10/01/2009 12:24 PM, Artem Ananiev wrote:
>>>>> I've quickly looked through the changes, the fix looks fine with 
>>>>> the exception of using double-check idiom in Container.validate() - 
>>>>> I told you about that the other day.
>>>>
>>>> To make sure we don't get messed up when discovering potential 
>>>> regressions, I've just filed a separate CR 6887249 (Get rid of 
>>>> double-check for isValid() idiom in validate() methods) to fix the 
>>>> issue later. Thanks for the suggestion.
>>>>
>>>> -- 
>>>> best regards,
>>>> Anthony
>>>>
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Artem
>>>>>
>>>>> Anthony Petrov wrote:
>>>>>> It's been a long time since we discussed the issue. Now is the 
>>>>>> time for revival.
>>>>>>
>>>>>> Last time we came across a failing test [1] that had a JApplet 
>>>>>> embedded in a JFrame. The frame was expected to be validated upon 
>>>>>> showing. However, the components in the JApplet were not 
>>>>>> validated, since the JApplet itself was marked valid, but the 
>>>>>> invalidate() requests from the children of the applet stopped on 
>>>>>> the RootPane of the JApplet because it was a validate root.
>>>>>>
>>>>>> Later we found out a possible solution for that problem [2]: the 
>>>>>> show() (as well as the pack()) should validate the whole component 
>>>>>> hierarchy unconditionally.
>>>>>>
>>>>>> So, here's the fix with this solution implemented. Please review:
>>>>>>
>>>>>> http://cr.openjdk.java.net/~anthony/7-23-invalidate-6852592.3/
>>>>>>
>>>>>> The fix has been tested quite thoroughly: all sort of related 
>>>>>> automatic tests for both Swing and AWT areas have been run 
>>>>>> (including layout-related tests, bare (J)Component and 
>>>>>> Container-related tests, and some other.) All manual 
>>>>>> layout-related tests from AWT and Swing have also been run and 
>>>>>> passed. Mixing-related regression tests pass as well.
>>>>>>
>>>>>> Please note that I've also changed the synopsis of the change 
>>>>>> request by replacing revalidate() with invalidate() because the 
>>>>>> fix actually affects the invalidate() method only.
>>>>>>
>>>>>> [1] 
>>>>>> http://mail.openjdk.java.net/pipermail/awt-dev/2009-August/000831.html 
>>>>>>
>>>>>>
>>>>>> [2] 
>>>>>> http://mail.openjdk.java.net/pipermail/awt-dev/2009-August/000835.html 
>>>>>>
>>>>>>
>>>>>> -- 
>>>>>> best regards,
>>>>>> Anthony
>>>
> 



More information about the awt-dev mailing list