RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

Aleksey Shipilev-5
SonarCloud reports multiple incorrect double-checked locking cases in `sun.java2d.CRenderer`. For example:

  Arc2D arcToShape;

  ...
            if (arcToShape == null) {
                synchronized (this) {
                    if (arcToShape == null) {
                        arcToShape = new Arc2D.Float();
                    }
                }
            }

`Arc2D` contains fields that are not `final`. `arcToShape` is not `volatile`. This makes it an incorrect DCL.
This code is used by Mac OS, do it would probably blow up some time later on M1.

This is the candidate fix that preserves the semantics. I am doing this fix blindly so far, without testing on real Mac OS. But maybe there is no need to do any of this, because the setter methods overwrite the contents of all these objects under their own sync. So, maybe we can just allocate those objects without DCL-backed caching and pass them in?

-------------

Commit messages:
 - JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

Changes: https://git.openjdk.java.net/jdk/pull/2948/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=2948&range=00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8263467
  Stats: 50 lines in 1 file changed: 15 ins; 0 del; 35 mod
  Patch: https://git.openjdk.java.net/jdk/pull/2948.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/2948/head:pull/2948

PR: https://git.openjdk.java.net/jdk/pull/2948
Reply | Threaded
Open this post in threaded view
|

Re: RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

Sergey Bylokhov-2
On Thu, 11 Mar 2021 19:13:47 GMT, Aleksey Shipilev <[hidden email]> wrote:

> SonarCloud reports multiple incorrect double-checked locking cases in `sun.java2d.CRenderer`. For example:
>
>   Arc2D arcToShape;
>
>   ...
>             if (arcToShape == null) {
>                 synchronized (this) {
>                     if (arcToShape == null) {
>                         arcToShape = new Arc2D.Float();
>                     }
>                 }
>             }
>
> `Arc2D` contains fields that are not `final`. `arcToShape` is not `volatile`. This makes it an incorrect DCL.
> This code is used by Mac OS, do it would probably blow up some time later on M1.
>
> This is the candidate fix that preserves the semantics. I am doing this fix blindly so far, without testing on real Mac OS. But maybe there is no need to do any of this, because the setter methods overwrite the contents of all these objects under their own sync. So, maybe we can just allocate those objects without DCL-backed caching and pass them in?

I guess "Incorrect double-checked" is a too strict description of this code, it just tried to eliminate the creation of one object and do not care about the content of that object, since it is immediately overridden.

I think It will be more clear to just eliminate this DCL since overhead and code complexity seems too much to just cache five objects.

Probably it was important in past(jdk6 and below) when this renderer was used for onscreen rendering. Currently, it is used for printing(if actually used at all).

-------------

PR: https://git.openjdk.java.net/jdk/pull/2948
Reply | Threaded
Open this post in threaded view
|

Re: RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer [v2]

Aleksey Shipilev-5
In reply to this post by Aleksey Shipilev-5
> SonarCloud reports multiple incorrect double-checked locking cases in `sun.java2d.CRenderer`. For example:
>
>   Arc2D arcToShape;
>
>   ...
>             if (arcToShape == null) {
>                 synchronized (this) {
>                     if (arcToShape == null) {
>                         arcToShape = new Arc2D.Float();
>                     }
>                 }
>             }
>
> `Arc2D` contains fields that are not `final`. `arcToShape` is not `volatile`. This makes it an incorrect DCL.
> This code is used by Mac OS, do it would probably blow up some time later on M1.
>
> This is the candidate fix that preserves the semantics. I am doing this fix blindly so far, without testing on real Mac OS. But maybe there is no need to do any of this, because the setter methods overwrite the contents of all these objects under their own sync. So, maybe we can just allocate those objects without DCL-backed caching and pass them in?

Aleksey Shipilev has updated the pull request incrementally with one additional commit since the last revision:

  Drop DCL and useless synchronization completely

-------------

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/2948/files
  - new: https://git.openjdk.java.net/jdk/pull/2948/files/c81b9ea2..d912f559

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk&pr=2948&range=01
 - incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=2948&range=00-01

  Stats: 80 lines in 1 file changed: 0 ins; 70 del; 10 mod
  Patch: https://git.openjdk.java.net/jdk/pull/2948.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/2948/head:pull/2948

PR: https://git.openjdk.java.net/jdk/pull/2948
Reply | Threaded
Open this post in threaded view
|

Re: RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

Aleksey Shipilev-5
In reply to this post by Sergey Bylokhov-2
On Fri, 12 Mar 2021 03:19:12 GMT, Sergey Bylokhov <[hidden email]> wrote:

>> SonarCloud reports multiple incorrect double-checked locking cases in `sun.java2d.CRenderer`. For example:
>>
>>   Arc2D arcToShape;
>>
>>   ...
>>             if (arcToShape == null) {
>>                 synchronized (this) {
>>                     if (arcToShape == null) {
>>                         arcToShape = new Arc2D.Float();
>>                     }
>>                 }
>>             }
>>
>> `Arc2D` contains fields that are not `final`. `arcToShape` is not `volatile`. This makes it an incorrect DCL.
>> This code is used by Mac OS, do it would probably blow up some time later on M1.
>>
>> This is the candidate fix that preserves the semantics. I am doing this fix blindly so far, without testing on real Mac OS. But maybe there is no need to do any of this, because the setter methods overwrite the contents of all these objects under their own sync. So, maybe we can just allocate those objects without DCL-backed caching and pass them in?
>
> I guess "Incorrect double-checked" is a too strict description of this code, it just tried to eliminate the creation of one object and do not care about the content of that object, since it is immediately overridden.
>
> I think It will be more clear to just eliminate this DCL since overhead and code complexity seems too much to just cache five objects.
>
> Probably it was important in past(jdk6 and below) when this renderer was used for onscreen rendering. Currently, it is used for printing(if actually used at all).

Ok, I removed the "DCL" from that code and used the objects directly. AFAICS, synchronization is redundant on those local objects. What would be a good test for this change?

-------------

PR: https://git.openjdk.java.net/jdk/pull/2948
Reply | Threaded
Open this post in threaded view
|

Re: RFR: JDK-8263467: Incorrect double-checked locking in sun.java2d.CRenderer

Sergey Bylokhov-2
On Fri, 12 Mar 2021 07:19:06 GMT, Aleksey Shipilev <[hidden email]> wrote:

> Ok, I removed the "DCL" from that code and used the objects directly. AFAICS, synchronization is redundant on those local objects. What would be a good test for this change?

I guess that synchronization became redundant because the field was moved to the local var. But before that, it guarded the method in question for multithreaded access and that was not part of the DCL. So it will be better to return those fields back.

As the test I have run all automated tests and some manual tests, none of them triggered this code.

-------------

PR: https://git.openjdk.java.net/jdk/pull/2948