[OpenJDK 2D-Dev] RFR: 6986863: ProfileDeferralMgr throwing ConcurrentModificationException

Sergey Bylokhov serb at openjdk.java.net
Fri Dec 4 02:30:14 UTC 2020

On Thu, 3 Dec 2020 23:52:25 GMT, Sergey Bylokhov <serb at openjdk.org> wrote:

> This change intended to enhance the lazy initialization of the standard color profiles concurrently by different threads.
> We defer standard profiles loading because most of UI application uses a small amount of data from the profile like numComponents and colorSpaceType, and this data is known in advance. But any other profile-related activity (like a color conversion, profile data accesses, etc.) triggers profile activation when we load all profile data to the memory.
> Before the fix for JDK-6793818, we defer only one sRGB color profile, see: https://github.com/openjdk/jdk/commit/2726f2a3621dd2562d4fb660b4c3d376c65027aa
> Notes about the link above:
> - The code in the ProfileDeferralMgr, which contain the Vector of profiles for activation does not use any synchronization
> - The `activateDeferredProfile` and `activate` methods are implemented to throw `ProfileDataException`, but this exception is ignored during activation process: 
>     https://github.com/openjdk/jdk/commit/2726f2a3621dd2562d4fb660b4c3d376c65027aa#diff-0839c25a6c999452be28b431c54d5daa91364d302cfda6efa5c56421c2f2bdcbR96
> The fix:
>  - Drops the usage of ProfileDeferralMgr (which contained the Vector of profiles for activation) and ProfileActivator machinery. Instead, we will have just one `ICC_Profile.activate()` method which will activate and initialize the `ICC_Profile.cmmProfile` if it is null
>  - The `activate` method implementation mimics the old behavior when the CMMException and IOException were wrapped by the ProfileDataException, and the ProfileDataException itself was ignored during activation - > so an exception will not be thrown in the method itself, but only when the null profile will be used.
> See some comments inline.

src/java.desktop/share/classes/java/awt/color/ICC_Profile.java line 1064:

> 1062:         ProfileDeferralInfo info = deferralInfo;
> 1063:         if (info != null) {
> 1064:             return info.profileClass;

Separate MT issue found by the code review, we can get NPE here if deferralInfo will be set to null(activated) after the null-check. Proved by the ProfileActivationDuringpropertyAccess test.

src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java line 72:

> 70:                          int transformType)
> 71:     {
> 72:         /* Actually, it is not a complete transform but just part of it */

We have to activate it here because later in this class we call:
76        lcmsProfiles[0] = LCMS.getProfileID(profile);
And that native method expects the activated profile, after the fix, we will activate it in that native method.

src/java.desktop/share/native/liblcms/LCMS.c line 652:

> 650:         return NULL;
> 651:     }
> 652: 

The purpose of this method is to bypass java access control and access the private ICC_Profile.cmmProfile field, I have added a call for activation here as well. This could be improved someday by the accessor or something like this.

src/java.desktop/share/classes/java/awt/color/ICC_Profile.java line 1001:

> 999:      * was ignored during activation.
> 1000:      */
> 1001:     private void activate() {

As of now, this code block is never executed, since we never pass ProfileDeferralInfo as an InputStream. probably we did it a long time ago.

src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java line 83:

> 81: 
> 82:     /**
> 83:      * Constructs a new ColorConvertOp which will convert

Seems unnecessary, this class uses the `sun.java2d.cmm.ColorTransform` which will load the profile when necessary.

src/java.desktop/share/classes/java/awt/color/ICC_Profile.java line 782:

> 780:             if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) &&
> 781:                 (getData (p, icSigMediaWhitePointTag) != null) &&
> 782:                 (getData (p, icSigGrayTRCTag) != null)) {

Why do we need to load standard profiles if the user wants to load some other profile from the data array?


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

More information about the 2d-dev mailing list