From dea4d8cd2a2450841469a289824281142bccacce Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 7 Jul 2025 22:25:20 -0700 Subject: [PATCH] 8359380: Rework deferral profile logic after JDK-8346465 --- .../classes/java/awt/color/ICC_Profile.java | 63 +++++++------------ .../java/awt/color/ICC_ProfileGray.java | 6 +- .../java/awt/color/ICC_ProfileRGB.java | 6 +- ...erralInfo.java => BuiltinProfileInfo.java} | 16 ++--- .../awt/color/CheckDefaultProperties.java | 38 ++++++----- .../BuiltInProfileCheck.java | 2 +- 6 files changed, 61 insertions(+), 70 deletions(-) rename src/java.desktop/share/classes/sun/java2d/cmm/{ProfileDeferralInfo.java => BuiltinProfileInfo.java} (74%) diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index 3793b138a969b..b6e292a051803 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -51,11 +51,11 @@ import java.util.StringTokenizer; import sun.awt.AWTAccessor; +import sun.java2d.cmm.BuiltinProfileInfo; import sun.java2d.cmm.CMSManager; import sun.java2d.cmm.PCMM; import sun.java2d.cmm.Profile; import sun.java2d.cmm.ProfileDataVerifier; -import sun.java2d.cmm.ProfileDeferralInfo; import static sun.java2d.cmm.ProfileDataVerifier.HEADER_SIZE; @@ -102,20 +102,11 @@ public sealed class ICC_Profile implements Serializable private transient volatile Profile cmmProfile; /** - * Stores some information about {@code ICC_Profile} without causing a - * deferred profile to be loaded. Note that we can defer the loading of - * standard profiles only. If this field is null, then {@link #cmmProfile} - * should be used to access profile information. + * Stores information about a built-in profile without triggering profile + * loading. If this field is null, {@link #cmmProfile} should be used to + * access profile data. If not null, the profile is considered immutable. */ - private transient volatile ProfileDeferralInfo deferralInfo; - - - /** - * Set to {@code true} for {@code BuiltInProfile}, {@code false} otherwise. - * This flag is used in {@link #setData(int, byte[])} to prevent modifying - * built-in profiles. - */ - private final transient boolean builtIn; + private transient final BuiltinProfileInfo builtInInfo; /** * The lazy registry of singleton profile objects for specific built-in @@ -124,22 +115,22 @@ public sealed class ICC_Profile implements Serializable */ private interface BuiltInProfile { /* - * ProfileDeferralInfo is used for built-in profile creation only, + * BuiltinProfileInfo is used for built-in profile creation only, * and all built-in profiles should be constructed using it. */ - ICC_Profile SRGB = new ICC_ProfileRGB(new ProfileDeferralInfo( + ICC_Profile SRGB = new ICC_ProfileRGB(new BuiltinProfileInfo( "sRGB.pf", ColorSpace.TYPE_RGB, 3, CLASS_DISPLAY)); - ICC_Profile LRGB = new ICC_ProfileRGB(new ProfileDeferralInfo( + ICC_Profile LRGB = new ICC_ProfileRGB(new BuiltinProfileInfo( "LINEAR_RGB.pf", ColorSpace.TYPE_RGB, 3, CLASS_DISPLAY)); - ICC_Profile XYZ = new ICC_Profile(new ProfileDeferralInfo( + ICC_Profile XYZ = new ICC_Profile(new BuiltinProfileInfo( "CIEXYZ.pf", ColorSpace.TYPE_XYZ, 3, CLASS_ABSTRACT)); - ICC_Profile PYCC = new ICC_Profile(new ProfileDeferralInfo( + ICC_Profile PYCC = new ICC_Profile(new BuiltinProfileInfo( "PYCC.pf", ColorSpace.TYPE_3CLR, 3, CLASS_COLORSPACECONVERSION)); - ICC_Profile GRAY = new ICC_ProfileGray(new ProfileDeferralInfo( + ICC_Profile GRAY = new ICC_ProfileGray(new BuiltinProfileInfo( "GRAY.pf", ColorSpace.TYPE_GRAY, 1, CLASS_DISPLAY)); } @@ -771,7 +762,7 @@ private interface BuiltInProfile { */ ICC_Profile(Profile p) { cmmProfile = p; - builtIn = false; + builtInInfo = null; } /** @@ -779,12 +770,11 @@ private interface BuiltInProfile { * The ID will be 0 until the profile is loaded. * *

- * Note: {@code ProfileDeferralInfo} is used for built-in profile + * Note: {@code BuiltinProfileInfo} is used for built-in profile * creation only, and all built-in profiles should be constructed using it. */ - ICC_Profile(ProfileDeferralInfo pdi) { - deferralInfo = pdi; - builtIn = true; + ICC_Profile(BuiltinProfileInfo pdi) { + builtInInfo = pdi; } /** @@ -934,7 +924,7 @@ private Profile cmmProfile() { if (cmmProfile != null) { return cmmProfile; } - var is = getStandardProfileInputStream(deferralInfo.filename); + var is = getStandardProfileInputStream(builtInInfo.filename); if (is == null) { return null; } @@ -942,8 +932,6 @@ private Profile cmmProfile() { byte[] data = getProfileDataFromStream(is); if (data != null) { p = cmmProfile = CMSManager.getModule().loadProfile(data); - // from now we cannot use the deferred value, drop it - deferralInfo = null; } } catch (CMMException | IOException ignore) { } @@ -975,9 +963,8 @@ public int getMinorVersion() { * @return one of the predefined profile class constants */ public int getProfileClass() { - ProfileDeferralInfo info = deferralInfo; - if (info != null) { - return info.profileClass; + if (builtInInfo != null) { + return builtInInfo.profileClass; } byte[] theHeader = getData(cmmProfile(), icSigHead); return getProfileClass(theHeader); @@ -1012,9 +999,8 @@ private static int getProfileClass(byte[] data) { * {@code ColorSpace} class */ public int getColorSpaceType() { - ProfileDeferralInfo info = deferralInfo; - if (info != null) { - return info.colorSpaceType; + if (builtInInfo != null) { + return builtInInfo.colorSpaceType; } byte[] theHeader = getData(cmmProfile(), icSigHead); return getColorSpaceType(theHeader); @@ -1160,8 +1146,8 @@ static byte[] getData(Profile p, int tagSignature) { * @see ColorSpace */ public void setData(int tagSignature, byte[] tagData) { - if (builtIn) { - throw new IllegalArgumentException("Built-in profile cannot be modified"); + if (builtInInfo != null) { + throw new IllegalArgumentException("Can't modify built-in profile"); } if (tagSignature == ICC_Profile.icSigHead) { @@ -1205,9 +1191,8 @@ private static void checkRenderingIntent(byte[] data) { * @throws ProfileDataException if color space is in the profile is invalid */ public int getNumComponents() { - ProfileDeferralInfo info = deferralInfo; - if (info != null) { - return info.numComponents; + if (builtInInfo != null) { + return builtInInfo.numComponents; } byte[] theHeader = getData(cmmProfile(), icSigHead); int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java index 523668d37ecc2..9421a1b7d03ad 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileGray.java @@ -37,8 +37,8 @@ import java.io.Serial; +import sun.java2d.cmm.BuiltinProfileInfo; import sun.java2d.cmm.Profile; -import sun.java2d.cmm.ProfileDeferralInfo; /** * The {@code ICC_ProfileGray} class is a subclass of the {@code ICC_Profile} @@ -87,9 +87,9 @@ public final class ICC_ProfileGray extends ICC_Profile { /** * Constructs a new {@code ICC_ProfileGray} from a - * {@code ProfileDeferralInfo} object. + * {@code BuiltinProfileInfo} object. */ - ICC_ProfileGray(ProfileDeferralInfo pdi) { + ICC_ProfileGray(BuiltinProfileInfo pdi) { super(pdi); } diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java index d46852380f352..f180242c0256a 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java @@ -37,8 +37,8 @@ import java.io.Serial; +import sun.java2d.cmm.BuiltinProfileInfo; import sun.java2d.cmm.Profile; -import sun.java2d.cmm.ProfileDeferralInfo; /** * The {@code ICC_ProfileRGB} class is a subclass of the {@code ICC_Profile} @@ -122,11 +122,11 @@ public final class ICC_ProfileRGB extends ICC_Profile { /** * Constructs a new {@code ICC_ProfileRGB} from a - * {@code ProfileDeferralInfo} object. + * {@code BuiltinProfileInfo} object. * * @param pdi */ - ICC_ProfileRGB(ProfileDeferralInfo pdi) { + ICC_ProfileRGB(BuiltinProfileInfo pdi) { super(pdi); } diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/ProfileDeferralInfo.java b/src/java.desktop/share/classes/sun/java2d/cmm/BuiltinProfileInfo.java similarity index 74% rename from src/java.desktop/share/classes/sun/java2d/cmm/ProfileDeferralInfo.java rename to src/java.desktop/share/classes/sun/java2d/cmm/BuiltinProfileInfo.java index 522ffa21453d9..f9f96235d3aa3 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/ProfileDeferralInfo.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/BuiltinProfileInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,15 +26,15 @@ package sun.java2d.cmm; /** - * A class to pass information about a profile to be loaded from a file to the - * static getInstance(int cspace) method of ICC_Profile. Loading of the profile - * data and initialization of the CMM is to be deferred as long as possible. + * Stores information about a built-in profile used by + * ICC_Profile.getInstance(int cspace) to defer the loading of profile data and + * CMM initialization. Since built-in profiles are immutable, this information + * is always valid. */ -public final class ProfileDeferralInfo { +public final class BuiltinProfileInfo { /** - * Need to have this info for ICC_ColorSpace without causing a deferred - * profile to be loaded. + * Used by ICC_ColorSpace without triggering built-in profile loading. */ public final int colorSpaceType, numComponents, profileClass; @@ -43,7 +43,7 @@ public final class ProfileDeferralInfo { */ public final String filename; - public ProfileDeferralInfo(String fn, int type, int ncomp, int pclass) { + public BuiltinProfileInfo(String fn, int type, int ncomp, int pclass) { filename = fn; colorSpaceType = type; numComponents = ncomp; diff --git a/test/jdk/java/awt/color/CheckDefaultProperties.java b/test/jdk/java/awt/color/CheckDefaultProperties.java index 583c46da7e10e..fd44a7e669bff 100644 --- a/test/jdk/java/awt/color/CheckDefaultProperties.java +++ b/test/jdk/java/awt/color/CheckDefaultProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,9 @@ /** * @test - * @bug 8256321 - * @summary Verifies profile properties are the same before/after activation + * @bug 8256321 8359380 + * @summary Verifies built-in profile properties are the same before and after + * activation and in copies of built-in profiles */ public final class CheckDefaultProperties { @@ -46,21 +47,26 @@ public static void main(String[] args) { ICC_Profile lrgb = ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB); ICC_Profile pycc = ICC_Profile.getInstance(ColorSpace.CS_PYCC); - // check default values, before profile activation - test(srgb, TYPE_RGB, 3, CLASS_DISPLAY); - test(gray, TYPE_GRAY, 1, CLASS_DISPLAY); - test(xyz, TYPE_XYZ, 3, CLASS_ABSTRACT); - test(lrgb, TYPE_RGB, 3, CLASS_DISPLAY); - test(pycc, TYPE_3CLR, 3, CLASS_COLORSPACECONVERSION); + // checks default values before built-in profiles are activated + test(srgb, gray, xyz, lrgb, pycc); + + // activates built-in profiles and creates copies + ICC_Profile srgbCopy = ICC_Profile.getInstance(srgb.getData()); + ICC_Profile grayCopy = ICC_Profile.getInstance(gray.getData()); + ICC_Profile xyzCopy = ICC_Profile.getInstance(xyz.getData()); + ICC_Profile lrgbCopy = ICC_Profile.getInstance(lrgb.getData()); + ICC_Profile pyccCopy = ICC_Profile.getInstance(pycc.getData()); - // activate profiles - srgb.getData(); - gray.getData(); - xyz.getData(); - lrgb.getData(); - pycc.getData(); + // checks default values after profile activation + test(srgb, gray, xyz, lrgb, pycc); + + // checks default values in copies of the built-in profiles + test(srgbCopy, grayCopy, xyzCopy, lrgbCopy, pyccCopy); + } - // check default values, after profile activation + private static void test(ICC_Profile srgb, ICC_Profile gray, + ICC_Profile xyz, ICC_Profile lrgb, + ICC_Profile pycc) { test(srgb, TYPE_RGB, 3, CLASS_DISPLAY); test(gray, TYPE_GRAY, 1, CLASS_DISPLAY); test(xyz, TYPE_XYZ, 3, CLASS_ABSTRACT); diff --git a/test/jdk/java/awt/color/ICC_Profile/BuiltInProfileCheck/BuiltInProfileCheck.java b/test/jdk/java/awt/color/ICC_Profile/BuiltInProfileCheck/BuiltInProfileCheck.java index 8f00ab1074717..6cc10c475507d 100644 --- a/test/jdk/java/awt/color/ICC_Profile/BuiltInProfileCheck/BuiltInProfileCheck.java +++ b/test/jdk/java/awt/color/ICC_Profile/BuiltInProfileCheck/BuiltInProfileCheck.java @@ -39,7 +39,7 @@ public class BuiltInProfileCheck { private static final int HEADER_TAG = ICC_Profile.icSigHead; private static final int INDEX = ICC_Profile.icHdrDeviceClass; - private static final String EXCEPTION_MSG = "Built-in profile cannot be modified"; + private static final String EXCEPTION_MSG = "Can't modify built-in profile"; /** * {@link #prepareTestProfile(String, boolean, int)} * stores the profile to test in testProfile.