RFR: JDK-6823527: java.util.logging.Handler has thread safety issues

David Holmes david.holmes at oracle.com
Fri Aug 30 07:21:00 UTC 2013

Hi Daniel,

I'm fine with the approach in (c), just wanted to highlight the 
performance considerations (volatile and synchronized need not be 
equivalent in the uncontended case - biased-locking can mean there are 
no barriers emitted.)

A few specific comments on [2]:


reportError doesn't need changing now that the field is volatile and you 
aren't doing sync.


pushLevel should/could be volatile and the sync removed from getPushLevel.

In setPushLevel this seems to be unused code:

  262         LogManager manager = LogManager.getLogManager();

unless there is some obscure side-effect in calling getLogManager ??

setPushLevel might as well also be synchronized at the method level. All 
the Handler methods already include checkPermission inside the 
sync-block. Though I'm actually more inclined to change all the existing 
code to use sync-blocks so that checkPermission is done outside the lock 
region. But a consistent approach either way would be preferable.


writer doesn't need to be volatile - AFAICS it is only accessed within 
synchronized methods.


On 30/08/2013 4:45 PM, Daniel Fuchs wrote:
> On 8/30/13 3:27 AM, David Holmes wrote:
>> Hi Daniel,
>> As usual with these kinds of changes we start by trying to complete an
>> incomplete/incorrect synchronization pattern and get diverted into
>> changing the synchronization pattern. :) The latter of course has more
>> risk than the former.
>> Making everything synchronized has the benefit that we don't need to
>> analyse the "real" methods to check what would happen if one of these
>> data values changed mid-method. Might be harmless, might not.
>> Atomicity makes things easy to reason about.
> Agreed. We can analyze the 'real methods' of Handler classes in the JDK.
> But I'm sure there are plenty of
> subclasses of handlers in applications out there that we don't know
> about. So we can't really be sure
> what the effect of changing synchronization might have on those subclasses.
>> Making the fields volatile and un-sync'ing the getters is a potential
>> optimization for readers. But are these fields that are read
>> frequently by multiple threads?
> At least three of them are accessed by isLoggable() which I believe is
> called very frequently by
> multiple threads (level, filter, and writer).
>> The downside of doing so is a negative performance impact inside the
>> "real" methods where every volatile field access requires
>> (platform-dependent) memory barriers.
> That - I think - should not be such an issue since the fields are private.
> I mean - we can see whether there are methods that do multiple access to
> the fields in the
> classes that define these fields - and fix that if necessary.
> For subclasses, they will have to call the getter, which will require
> synchronization anyway.
> I mean - for subclasses - isn't the fact that the getter accesses a
> volatile field or the fact that the
> getter is synchronized equivalent in terms of performance?
> JDK 8 is a major version of the JDK - so I think if we want to fix this
> bug it's
> probably better to do it now rather than in a minor update.
> It seems we have 5 choices:
> a. Not fixing
> b. Using regular 'synchronized' pattern [1]
> c. Using volatiles, synchronize setters only [2]
> d. Using volatiles, only synchronize setters when obviously necessary
> e. other? (like introducing new private locks - but I don't think
> anybody would want that)
> [1] <http://cr.openjdk.java.net/~dfuchs/webrev_6823527/webrev.00/>
> [2] <http://cr.openjdk.java.net/~dfuchs/webrev_6823527/webrev.01/>
> My own preference would lean to either b) or c).
> -- daniel
>> David
>> On 30/08/2013 5:54 AM, Daniel Fuchs wrote:
>>> On 8/29/13 9:45 PM, Mandy Chung wrote:
>>>> On 8/29/13 11:04 AM, Daniel Fuchs wrote:
>>>>> On 8/29/13 7:58 PM, Mandy Chung wrote:
>>>>>> On 8/29/13 9:46 AM, Daniel Fuchs wrote:
>>>>>>> Here is the new webrev implementing Jason's suggestion.
>>>>>>> Compared to previous webrev only Handler.java & StreamHandler.java
>>>>>>> have changed.
>>>>>>> <http://cr.openjdk.java.net/~dfuchs/webrev_6823527/webrev.01/>
>>>>>> Looks good.  I also agree that making those fields to be volatile
>>>>>> is a
>>>>>> good suggestion and only requires writer to acquire the lock.
>>>>>> A minor comment:  The setter methods in Handler class are
>>>>>> synchronized
>>>>>> at the method entry whereas StreamHandler.setPushLevel synchronizes
>>>>>> after checkPermission() is called.  checkPermission doesn't need
>>>>>> to be
>>>>>> synchronized.  Either way is fine with me and it'd be good to do it
>>>>>> consistently.
>>>>> Hi Mandy,
>>>>> Are you suggesting I should put checkPermission() within
>>>>> the synchronized block? It might be more consistent with
>>>>> what the other setters do. Although as you state it does
>>>>> not matter much.
>>>> Having a second thought - do the setters really need to be
>>>> synchronized?   My guess is that StreamHandler.publish is synchronized
>>>> so as to ensure that the log messages are sequential and not
>>>> interpersed
>>>> when multiple threads are publishing.  The spec is unclear. Perhaps it
>>>> worths looking into this further?
>>> I believe at least setEncodings() needs synchronization.
>>> setLevel() had it - so are we going to cause subtle race conditions
>>> if we remove it?
>>> My own feeling is that keeping setters synchronized might be better.
>>> We could of course say that a subclass which needs to prevent
>>> e.g. setFormatter() from being called concurrently with publish()
>>> should override setFormatter just for the purpose of synchronizing
>>> it...
>>>> One more minor note: MemoryHandler.pushLevel can also be made volatile.
>>>> L262: look like the log manager is not needed in the existing code.
>>> hmmm. Right. It's already called once in the super class so removing
>>> this call should have no effect. I will remove it.
>>> -- daniel
>>>> Mandy

More information about the core-libs-dev mailing list