Skip to content

Commit 64a150c

Browse files
committed
6986863: ProfileDeferralMgr throwing ConcurrentModificationException
Reviewed-by: kizune
1 parent ea2c447 commit 64a150c

File tree

9 files changed

+255
-337
lines changed

9 files changed

+255
-337
lines changed

src/java.desktop/share/classes/java/awt/color/ICC_Profile.java

Lines changed: 54 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,8 @@
5555
import sun.java2d.cmm.CMSManager;
5656
import sun.java2d.cmm.PCMM;
5757
import sun.java2d.cmm.Profile;
58-
import sun.java2d.cmm.ProfileActivator;
5958
import sun.java2d.cmm.ProfileDataVerifier;
6059
import sun.java2d.cmm.ProfileDeferralInfo;
61-
import sun.java2d.cmm.ProfileDeferralMgr;
6260

6361
/**
6462
* A representation of color profile data for device independent and device
@@ -93,10 +91,8 @@ public class ICC_Profile implements Serializable {
9391
@Serial
9492
private static final long serialVersionUID = -3938515861990936766L;
9593

96-
private transient Profile cmmProfile;
97-
98-
private transient ProfileDeferralInfo deferralInfo;
99-
private transient ProfileActivator profileActivator;
94+
private transient volatile Profile cmmProfile;
95+
private transient volatile ProfileDeferralInfo deferralInfo;
10096

10197
// Registry of singleton profile objects for specific color spaces
10298
// defined in the ColorSpace class (e.g. CS_sRGB), see
@@ -731,21 +727,15 @@ public class ICC_Profile implements Serializable {
731727
* Constructs an {@code ICC_Profile} object with a given ID.
732728
*/
733729
ICC_Profile(Profile p) {
734-
this.cmmProfile = p;
730+
cmmProfile = p;
735731
}
736732

737733
/**
738734
* Constructs an {@code ICC_Profile} object whose loading will be deferred.
739735
* The ID will be 0 until the profile is loaded.
740736
*/
741737
ICC_Profile(ProfileDeferralInfo pdi) {
742-
this.deferralInfo = pdi;
743-
this.profileActivator = new ProfileActivator() {
744-
public void activate() throws ProfileDataException {
745-
activateDeferredProfile();
746-
}
747-
};
748-
ProfileDeferralMgr.registerDeferral(this.profileActivator);
738+
deferralInfo = pdi;
749739
}
750740

751741
/**
@@ -780,10 +770,6 @@ public static ICC_Profile getInstance(byte[] data) {
780770

781771
Profile p = null;
782772

783-
if (ProfileDeferralMgr.deferring) {
784-
ProfileDeferralMgr.activateProfiles();
785-
}
786-
787773
ProfileDataVerifier.verify(data);
788774

789775
try {
@@ -842,11 +828,11 @@ public static ICC_Profile getInstance (int cspace) {
842828
* Enabling the appropriate access privileges is handled
843829
* at a lower level.
844830
*/
845-
ProfileDeferralInfo pInfo =
831+
ProfileDeferralInfo pdi =
846832
new ProfileDeferralInfo("sRGB.pf",
847833
ColorSpace.TYPE_RGB, 3,
848834
CLASS_DISPLAY);
849-
sRGBprofile = getDeferredInstance(pInfo);
835+
sRGBprofile = new ICC_ProfileRGB(pdi);
850836
}
851837
thisProfile = sRGBprofile;
852838
}
@@ -856,11 +842,11 @@ public static ICC_Profile getInstance (int cspace) {
856842
case ColorSpace.CS_CIEXYZ:
857843
synchronized(ICC_Profile.class) {
858844
if (XYZprofile == null) {
859-
ProfileDeferralInfo pInfo =
845+
ProfileDeferralInfo pdi =
860846
new ProfileDeferralInfo("CIEXYZ.pf",
861847
ColorSpace.TYPE_XYZ, 3,
862848
CLASS_ABSTRACT);
863-
XYZprofile = getDeferredInstance(pInfo);
849+
XYZprofile = new ICC_Profile(pdi);
864850
}
865851
thisProfile = XYZprofile;
866852
}
@@ -870,11 +856,11 @@ public static ICC_Profile getInstance (int cspace) {
870856
case ColorSpace.CS_PYCC:
871857
synchronized(ICC_Profile.class) {
872858
if (PYCCprofile == null) {
873-
ProfileDeferralInfo pInfo =
859+
ProfileDeferralInfo pdi =
874860
new ProfileDeferralInfo("PYCC.pf",
875861
ColorSpace.TYPE_3CLR, 3,
876862
CLASS_COLORSPACECONVERSION);
877-
PYCCprofile = getDeferredInstance(pInfo);
863+
PYCCprofile = new ICC_Profile(pdi);
878864
}
879865
thisProfile = PYCCprofile;
880866
}
@@ -884,11 +870,11 @@ public static ICC_Profile getInstance (int cspace) {
884870
case ColorSpace.CS_GRAY:
885871
synchronized(ICC_Profile.class) {
886872
if (GRAYprofile == null) {
887-
ProfileDeferralInfo pInfo =
873+
ProfileDeferralInfo pdi =
888874
new ProfileDeferralInfo("GRAY.pf",
889875
ColorSpace.TYPE_GRAY, 1,
890876
CLASS_DISPLAY);
891-
GRAYprofile = getDeferredInstance(pInfo);
877+
GRAYprofile = new ICC_ProfileGray(pdi);
892878
}
893879
thisProfile = GRAYprofile;
894880
}
@@ -898,11 +884,11 @@ public static ICC_Profile getInstance (int cspace) {
898884
case ColorSpace.CS_LINEAR_RGB:
899885
synchronized(ICC_Profile.class) {
900886
if (LINEAR_RGBprofile == null) {
901-
ProfileDeferralInfo pInfo =
887+
ProfileDeferralInfo pdi =
902888
new ProfileDeferralInfo("LINEAR_RGB.pf",
903889
ColorSpace.TYPE_RGB, 3,
904890
CLASS_DISPLAY);
905-
LINEAR_RGBprofile = getDeferredInstance(pInfo);
891+
LINEAR_RGBprofile = new ICC_ProfileRGB(pdi);
906892
}
907893
thisProfile = LINEAR_RGBprofile;
908894
}
@@ -916,26 +902,6 @@ public static ICC_Profile getInstance (int cspace) {
916902
return thisProfile;
917903
}
918904

919-
/**
920-
* This method asserts system privileges, so is used only for the standard
921-
* profiles.
922-
*/
923-
private static ICC_Profile getStandardProfile(final String name) {
924-
return AccessController.doPrivileged(
925-
new PrivilegedAction<ICC_Profile>() {
926-
public ICC_Profile run() {
927-
ICC_Profile p = null;
928-
try {
929-
p = getInstance(name);
930-
} catch (IOException ex) {
931-
throw new IllegalArgumentException(
932-
"Can't load standard profile: " + name);
933-
}
934-
return p;
935-
}
936-
});
937-
}
938-
939905
/**
940906
* Constructs an {@code ICC_Profile} corresponding to the data in a file.
941907
* {@code fileName} may be an absolute or a relative file specification.
@@ -997,13 +963,7 @@ public static ICC_Profile getInstance(String fileName) throws IOException {
997963
* Profile data
998964
*/
999965
public static ICC_Profile getInstance(InputStream s) throws IOException {
1000-
byte[] profileData;
1001-
1002-
if (s instanceof ProfileDeferralInfo) {
1003-
/* hack to detect profiles whose loading can be deferred */
1004-
return getDeferredInstance((ProfileDeferralInfo) s);
1005-
}
1006-
966+
byte[] profileData;
1007967
if ((profileData = getProfileDataFromStream(s)) == null) {
1008968
throw new IllegalArgumentException("Invalid ICC Profile Data");
1009969
}
@@ -1035,61 +995,32 @@ static byte[] getProfileDataFromStream(InputStream s) throws IOException {
1035995
}
1036996

1037997
/**
1038-
* Constructs an {@code ICC_Profile} for which the actual loading of the
1039-
* profile data from a file and the initialization of the CMM should be
1040-
* deferred as long as possible. Deferral is only used for standard
1041-
* profiles. If deferring is disabled, then getStandardProfile() ensures
1042-
* that all of the appropriate access privileges are granted when loading
1043-
* this profile. If deferring is enabled, then the deferred activation code
1044-
* will take care of access privileges.
1045-
*
1046-
* @see #activateDeferredProfile()
998+
* Activates the deferred standard profiles. Implementation of this method
999+
* mimics the old behaviour when the CMMException and IOException were
1000+
* wrapped by the ProfileDataException, and the ProfileDataException itself
1001+
* was ignored during activation.
10471002
*/
1048-
static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
1049-
if (!ProfileDeferralMgr.deferring) {
1050-
return getStandardProfile(pdi.filename);
1051-
}
1052-
if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
1053-
return new ICC_ProfileRGB(pdi);
1054-
} else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
1055-
return new ICC_ProfileGray(pdi);
1056-
} else {
1057-
return new ICC_Profile(pdi);
1058-
}
1059-
}
1060-
1061-
1062-
void activateDeferredProfile() throws ProfileDataException {
1063-
byte[] profileData;
1064-
final String fileName = deferralInfo.filename;
1065-
1066-
profileActivator = null;
1067-
deferralInfo = null;
1068-
InputStream is = getStandardProfileInputStream(fileName);
1069-
if (is == null) {
1070-
throw new ProfileDataException("Cannot open file " + fileName);
1071-
}
1072-
try {
1073-
profileData = getProfileDataFromStream(is);
1074-
is.close(); /* close the file */
1075-
}
1076-
catch (IOException e) {
1077-
ProfileDataException pde = new
1078-
ProfileDataException("Invalid ICC Profile Data" + fileName);
1079-
pde.initCause(e);
1080-
throw pde;
1081-
}
1082-
if (profileData == null) {
1083-
throw new ProfileDataException("Invalid ICC Profile Data" +
1084-
fileName);
1085-
}
1086-
try {
1087-
cmmProfile = CMSManager.getModule().loadProfile(profileData);
1088-
} catch (CMMException c) {
1089-
ProfileDataException pde = new
1090-
ProfileDataException("Invalid ICC Profile Data" + fileName);
1091-
pde.initCause(c);
1092-
throw pde;
1003+
private void activate() {
1004+
if (cmmProfile == null) {
1005+
synchronized (this) {
1006+
if (cmmProfile != null) {
1007+
return;
1008+
}
1009+
var is = getStandardProfileInputStream(deferralInfo.filename);
1010+
if (is == null) {
1011+
return;
1012+
}
1013+
try {
1014+
byte[] data = getProfileDataFromStream(is);
1015+
if (data != null) {
1016+
cmmProfile = CMSManager.getModule().loadProfile(data);
1017+
// from now we cannot use the deferred value, drop it
1018+
deferralInfo = null;
1019+
}
1020+
is.close(); /* close the stream */
1021+
} catch (CMMException | IOException ignore) {
1022+
}
1023+
}
10931024
}
10941025
}
10951026

@@ -1130,11 +1061,9 @@ public int getProfileClass() {
11301061
byte[] theHeader;
11311062
int theClassSig, theClass;
11321063

1133-
if (deferralInfo != null) {
1134-
return deferralInfo.profileClass; /* Need to have this info for
1135-
ICC_ColorSpace without
1136-
causing a deferred profile
1137-
to be loaded */
1064+
ProfileDeferralInfo info = deferralInfo;
1065+
if (info != null) {
1066+
return info.profileClass;
11381067
}
11391068

11401069
theHeader = getData(icSigHead);
@@ -1190,12 +1119,11 @@ public int getProfileClass() {
11901119
* {@code ColorSpace} class
11911120
*/
11921121
public int getColorSpaceType() {
1193-
if (deferralInfo != null) {
1194-
return deferralInfo.colorSpaceType; /* Need to have this info for
1195-
ICC_ColorSpace without
1196-
causing a deferred profile
1197-
to be loaded */
1122+
ProfileDeferralInfo info = deferralInfo;
1123+
if (info != null) {
1124+
return info.colorSpaceType;
11981125
}
1126+
activate();
11991127
return getColorSpaceType(cmmProfile);
12001128
}
12011129

@@ -1223,9 +1151,7 @@ static int getColorSpaceType(Profile p) {
12231151
* {@code ColorSpace} class
12241152
*/
12251153
public int getPCSType() {
1226-
if (ProfileDeferralMgr.deferring) {
1227-
ProfileDeferralMgr.activateProfiles();
1228-
}
1154+
activate();
12291155
return getPCSType(cmmProfile);
12301156
}
12311157

@@ -1283,9 +1209,7 @@ public byte[] getData() {
12831209
int profileSize;
12841210
byte[] profileData;
12851211

1286-
if (ProfileDeferralMgr.deferring) {
1287-
ProfileDeferralMgr.activateProfiles();
1288-
}
1212+
activate();
12891213

12901214
PCMM mdl = CMSManager.getModule();
12911215

@@ -1315,9 +1239,7 @@ public byte[] getData() {
13151239
*/
13161240
public byte[] getData(int tagSignature) {
13171241

1318-
if (ProfileDeferralMgr.deferring) {
1319-
ProfileDeferralMgr.activateProfiles();
1320-
}
1242+
activate();
13211243

13221244
return getData(cmmProfile, tagSignature);
13231245
}
@@ -1363,9 +1285,7 @@ static byte[] getData(Profile p, int tagSignature) {
13631285
*/
13641286
public void setData(int tagSignature, byte[] tagData) {
13651287

1366-
if (ProfileDeferralMgr.deferring) {
1367-
ProfileDeferralMgr.activateProfiles();
1368-
}
1288+
activate();
13691289

13701290
CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
13711291
}
@@ -1417,11 +1337,9 @@ public int getNumComponents() {
14171337
byte[] theHeader;
14181338
int theColorSpaceSig, theNumComponents;
14191339

1420-
if (deferralInfo != null) {
1421-
return deferralInfo.numComponents; /* Need to have this info for
1422-
ICC_ColorSpace without
1423-
causing a deferred profile
1424-
to be loaded */
1340+
ProfileDeferralInfo info = deferralInfo;
1341+
if (info != null) {
1342+
return info.numComponents;
14251343
}
14261344
theHeader = getData(icSigHead);
14271345

src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,16 +36,18 @@
3636

3737
package java.awt.image;
3838

39-
import java.awt.Point;
4039
import java.awt.Graphics2D;
41-
import java.awt.color.*;
42-
import sun.java2d.cmm.ColorTransform;
40+
import java.awt.Point;
41+
import java.awt.RenderingHints;
42+
import java.awt.color.ColorSpace;
43+
import java.awt.color.ICC_ColorSpace;
44+
import java.awt.color.ICC_Profile;
45+
import java.awt.geom.Point2D;
46+
import java.awt.geom.Rectangle2D;
47+
4348
import sun.java2d.cmm.CMSManager;
44-
import sun.java2d.cmm.ProfileDeferralMgr;
49+
import sun.java2d.cmm.ColorTransform;
4550
import sun.java2d.cmm.PCMM;
46-
import java.awt.geom.Rectangle2D;
47-
import java.awt.geom.Point2D;
48-
import java.awt.RenderingHints;
4951

5052
/**
5153
* This class performs a pixel-by-pixel color conversion of the data in
@@ -77,13 +79,6 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp {
7779
boolean gotProfiles;
7880
float[] srcMinVals, srcMaxVals, dstMinVals, dstMaxVals;
7981

80-
/* the class initializer */
81-
static {
82-
if (ProfileDeferralMgr.deferring) {
83-
ProfileDeferralMgr.activateProfiles();
84-
}
85-
}
86-
8782
/**
8883
* Constructs a new ColorConvertOp which will convert
8984
* from a source color space to a destination color space.

0 commit comments

Comments
 (0)