Skip to content

Commit 322a0c9

Browse files
antonvozniajankratochvil
authored andcommitted
6986863: ProfileDeferralMgr throwing ConcurrentModificationException
Reviewed-by: kizune
1 parent 1fade41 commit 322a0c9

File tree

7 files changed

+272
-183
lines changed

7 files changed

+272
-183
lines changed

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

Lines changed: 73 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025, 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
@@ -40,9 +40,7 @@
4040
import sun.java2d.cmm.CMSManager;
4141
import sun.java2d.cmm.Profile;
4242
import sun.java2d.cmm.ProfileDataVerifier;
43-
import sun.java2d.cmm.ProfileDeferralMgr;
4443
import sun.java2d.cmm.ProfileDeferralInfo;
45-
import sun.java2d.cmm.ProfileActivator;
4644
import sun.misc.IOUtils;
4745

4846
import java.io.BufferedInputStream;
@@ -57,6 +55,7 @@
5755
import java.io.ObjectStreamException;
5856
import java.io.OutputStream;
5957
import java.io.Serializable;
58+
import java.io.FilePermission;
6059

6160
import java.util.StringTokenizer;
6261

@@ -97,10 +96,8 @@ public class ICC_Profile implements Serializable {
9796

9897
private static final long serialVersionUID = -3938515861990936766L;
9998

100-
private transient Profile cmmProfile;
101-
102-
private transient ProfileDeferralInfo deferralInfo;
103-
private transient ProfileActivator profileActivator;
99+
private transient volatile Profile cmmProfile;
100+
private transient volatile ProfileDeferralInfo deferralInfo;
104101

105102
// Registry of singleton profile objects for specific color spaces
106103
// defined in the ColorSpace class (e.g. CS_sRGB), see
@@ -740,13 +737,7 @@ public class ICC_Profile implements Serializable {
740737
* The ID will be 0 until the profile is loaded.
741738
*/
742739
ICC_Profile(ProfileDeferralInfo pdi) {
743-
this.deferralInfo = pdi;
744-
this.profileActivator = new ProfileActivator() {
745-
public void activate() throws ProfileDataException {
746-
activateDeferredProfile();
747-
}
748-
};
749-
ProfileDeferralMgr.registerDeferral(this.profileActivator);
740+
deferralInfo = pdi;
750741
}
751742

752743

@@ -756,8 +747,6 @@ public void activate() throws ProfileDataException {
756747
protected void finalize () {
757748
if (cmmProfile != null) {
758749
CMSManager.getModule().freeProfile(cmmProfile);
759-
} else if (profileActivator != null) {
760-
ProfileDeferralMgr.unregisterDeferral(profileActivator);
761750
}
762751
}
763752

@@ -775,10 +764,6 @@ public static ICC_Profile getInstance(byte[] data) {
775764

776765
Profile p = null;
777766

778-
if (ProfileDeferralMgr.deferring) {
779-
ProfileDeferralMgr.activateProfiles();
780-
}
781-
782767
ProfileDataVerifier.verify(data);
783768

784769
try {
@@ -842,11 +827,11 @@ public static ICC_Profile getInstance (int cspace) {
842827
* Enabling the appropriate access privileges is handled
843828
* at a lower level.
844829
*/
845-
ProfileDeferralInfo pInfo =
830+
ProfileDeferralInfo pdi =
846831
new ProfileDeferralInfo("sRGB.pf",
847832
ColorSpace.TYPE_RGB, 3,
848833
CLASS_DISPLAY);
849-
sRGBprofile = getDeferredInstance(pInfo);
834+
sRGBprofile = new ICC_ProfileRGB(pdi);
850835
}
851836
thisProfile = sRGBprofile;
852837
}
@@ -856,11 +841,11 @@ public static ICC_Profile getInstance (int cspace) {
856841
case ColorSpace.CS_CIEXYZ:
857842
synchronized(ICC_Profile.class) {
858843
if (XYZprofile == null) {
859-
ProfileDeferralInfo pInfo =
844+
ProfileDeferralInfo pdi =
860845
new ProfileDeferralInfo("CIEXYZ.pf",
861846
ColorSpace.TYPE_XYZ, 3,
862-
CLASS_DISPLAY);
863-
XYZprofile = getDeferredInstance(pInfo);
847+
CLASS_ABSTRACT);
848+
XYZprofile = new ICC_Profile(pdi);
864849
}
865850
thisProfile = XYZprofile;
866851
}
@@ -872,11 +857,11 @@ public static ICC_Profile getInstance (int cspace) {
872857
if (PYCCprofile == null) {
873858
if (standardProfileExists("PYCC.pf"))
874859
{
875-
ProfileDeferralInfo pInfo =
860+
ProfileDeferralInfo pdi =
876861
new ProfileDeferralInfo("PYCC.pf",
877862
ColorSpace.TYPE_3CLR, 3,
878-
CLASS_DISPLAY);
879-
PYCCprofile = getDeferredInstance(pInfo);
863+
CLASS_COLORSPACECONVERSION);
864+
PYCCprofile = new ICC_Profile(pdi);
880865
} else {
881866
throw new IllegalArgumentException(
882867
"Can't load standard profile: PYCC.pf");
@@ -890,11 +875,11 @@ public static ICC_Profile getInstance (int cspace) {
890875
case ColorSpace.CS_GRAY:
891876
synchronized(ICC_Profile.class) {
892877
if (GRAYprofile == null) {
893-
ProfileDeferralInfo pInfo =
878+
ProfileDeferralInfo pdi =
894879
new ProfileDeferralInfo("GRAY.pf",
895880
ColorSpace.TYPE_GRAY, 1,
896881
CLASS_DISPLAY);
897-
GRAYprofile = getDeferredInstance(pInfo);
882+
GRAYprofile = new ICC_ProfileGray(pdi);
898883
}
899884
thisProfile = GRAYprofile;
900885
}
@@ -904,11 +889,11 @@ public static ICC_Profile getInstance (int cspace) {
904889
case ColorSpace.CS_LINEAR_RGB:
905890
synchronized(ICC_Profile.class) {
906891
if (LINEAR_RGBprofile == null) {
907-
ProfileDeferralInfo pInfo =
892+
ProfileDeferralInfo pdi =
908893
new ProfileDeferralInfo("LINEAR_RGB.pf",
909894
ColorSpace.TYPE_RGB, 3,
910895
CLASS_DISPLAY);
911-
LINEAR_RGBprofile = getDeferredInstance(pInfo);
896+
LINEAR_RGBprofile = new ICC_ProfileRGB(pdi);
912897
}
913898
thisProfile = LINEAR_RGBprofile;
914899
}
@@ -1005,13 +990,7 @@ public static ICC_Profile getInstance(String fileName) throws IOException {
1005990
* contain valid ICC Profile data.
1006991
*/
1007992
public static ICC_Profile getInstance(InputStream s) throws IOException {
1008-
byte profileData[];
1009-
1010-
if (s instanceof ProfileDeferralInfo) {
1011-
/* hack to detect profiles whose loading can be deferred */
1012-
return getDeferredInstance((ProfileDeferralInfo) s);
1013-
}
1014-
993+
byte[] profileData;
1015994
if ((profileData = getProfileDataFromStream(s)) == null) {
1016995
throw new IllegalArgumentException("Invalid ICC Profile Data");
1017996
}
@@ -1044,73 +1023,32 @@ static byte[] getProfileDataFromStream(InputStream s) throws IOException {
10441023

10451024

10461025
/**
1047-
* Constructs an ICC_Profile for which the actual loading of the
1048-
* profile data from a file and the initialization of the CMM should
1049-
* be deferred as long as possible.
1050-
* Deferral is only used for standard profiles.
1051-
* If deferring is disabled, then getStandardProfile() ensures
1052-
* that all of the appropriate access privileges are granted
1053-
* when loading this profile.
1054-
* If deferring is enabled, then the deferred activation
1055-
* code will take care of access privileges.
1056-
* @see activateDeferredProfile()
1026+
* Activates the deferred standard profiles. Implementation of this method
1027+
* mimics the old behaviour when the CMMException and IOException were
1028+
* wrapped by the ProfileDataException, and the ProfileDataException itself
1029+
* was ignored during activation.
10571030
*/
1058-
static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
1059-
if (!ProfileDeferralMgr.deferring) {
1060-
return getStandardProfile(pdi.filename);
1061-
}
1062-
if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
1063-
return new ICC_ProfileRGB(pdi);
1064-
} else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
1065-
return new ICC_ProfileGray(pdi);
1066-
} else {
1067-
return new ICC_Profile(pdi);
1068-
}
1069-
}
1070-
1071-
1072-
void activateDeferredProfile() throws ProfileDataException {
1073-
byte profileData[];
1074-
FileInputStream fis;
1075-
final String fileName = deferralInfo.filename;
1076-
1077-
profileActivator = null;
1078-
deferralInfo = null;
1079-
PrivilegedAction<FileInputStream> pa = new PrivilegedAction<FileInputStream>() {
1080-
public FileInputStream run() {
1081-
File f = getStandardProfileFile(fileName);
1082-
if (f != null) {
1083-
try {
1084-
return new FileInputStream(f);
1085-
} catch (FileNotFoundException e) {}
1031+
private void activate() {
1032+
if (cmmProfile == null) {
1033+
synchronized (this) {
1034+
if (cmmProfile != null) {
1035+
return;
1036+
}
1037+
InputStream is = getStandardProfileInputStream(deferralInfo.filename);
1038+
if (is == null) {
1039+
return;
1040+
}
1041+
try {
1042+
byte[] data = getProfileDataFromStream(is);
1043+
if (data != null) {
1044+
cmmProfile = CMSManager.getModule().loadProfile(data);
1045+
// from now we cannot use the deferred value, drop it
1046+
deferralInfo = null;
1047+
}
1048+
is.close(); /* close the stream */
1049+
} catch (CMMException | IOException ignore) {
10861050
}
1087-
return null;
10881051
}
1089-
};
1090-
if ((fis = AccessController.doPrivileged(pa)) == null) {
1091-
throw new ProfileDataException("Cannot open file " + fileName);
1092-
}
1093-
try {
1094-
profileData = getProfileDataFromStream(fis);
1095-
fis.close(); /* close the file */
1096-
}
1097-
catch (IOException e) {
1098-
ProfileDataException pde = new
1099-
ProfileDataException("Invalid ICC Profile Data" + fileName);
1100-
pde.initCause(e);
1101-
throw pde;
1102-
}
1103-
if (profileData == null) {
1104-
throw new ProfileDataException("Invalid ICC Profile Data" +
1105-
fileName);
1106-
}
1107-
try {
1108-
cmmProfile = CMSManager.getModule().loadProfile(profileData);
1109-
} catch (CMMException c) {
1110-
ProfileDataException pde = new
1111-
ProfileDataException("Invalid ICC Profile Data" + fileName);
1112-
pde.initCause(c);
1113-
throw pde;
11141052
}
11151053
}
11161054

@@ -1149,11 +1087,9 @@ public int getProfileClass() {
11491087
byte[] theHeader;
11501088
int theClassSig, theClass;
11511089

1152-
if (deferralInfo != null) {
1153-
return deferralInfo.profileClass; /* Need to have this info for
1154-
ICC_ColorSpace without
1155-
causing a deferred profile
1156-
to be loaded */
1090+
ProfileDeferralInfo info = deferralInfo;
1091+
if (info != null) {
1092+
return info.profileClass;
11571093
}
11581094

11591095
theHeader = getData(icSigHead);
@@ -1209,12 +1145,11 @@ public int getProfileClass() {
12091145
* <CODE>ColorSpace</CODE> class.
12101146
*/
12111147
public int getColorSpaceType() {
1212-
if (deferralInfo != null) {
1213-
return deferralInfo.colorSpaceType; /* Need to have this info for
1214-
ICC_ColorSpace without
1215-
causing a deferred profile
1216-
to be loaded */
1148+
ProfileDeferralInfo info = deferralInfo;
1149+
if (info != null) {
1150+
return info.colorSpaceType;
12171151
}
1152+
activate();
12181153
return getColorSpaceType(cmmProfile);
12191154
}
12201155

@@ -1241,9 +1176,7 @@ static int getColorSpaceType(Profile p) {
12411176
* <CODE>ColorSpace</CODE> class.
12421177
*/
12431178
public int getPCSType() {
1244-
if (ProfileDeferralMgr.deferring) {
1245-
ProfileDeferralMgr.activateProfiles();
1246-
}
1179+
activate();
12471180
return getPCSType(cmmProfile);
12481181
}
12491182

@@ -1305,9 +1238,7 @@ public byte[] getData() {
13051238
int profileSize;
13061239
byte[] profileData;
13071240

1308-
if (ProfileDeferralMgr.deferring) {
1309-
ProfileDeferralMgr.activateProfiles();
1310-
}
1241+
activate();
13111242

13121243
PCMM mdl = CMSManager.getModule();
13131244

@@ -1340,9 +1271,7 @@ public byte[] getData() {
13401271
*/
13411272
public byte[] getData(int tagSignature) {
13421273

1343-
if (ProfileDeferralMgr.deferring) {
1344-
ProfileDeferralMgr.activateProfiles();
1345-
}
1274+
activate();
13461275

13471276
return getData(cmmProfile, tagSignature);
13481277
}
@@ -1388,9 +1317,7 @@ static byte[] getData(Profile p, int tagSignature) {
13881317
*/
13891318
public void setData(int tagSignature, byte[] tagData) {
13901319

1391-
if (ProfileDeferralMgr.deferring) {
1392-
ProfileDeferralMgr.activateProfiles();
1393-
}
1320+
activate();
13941321

13951322
CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
13961323
}
@@ -1448,11 +1375,9 @@ public int getNumComponents() {
14481375
byte[] theHeader;
14491376
int theColorSpaceSig, theNumComponents;
14501377

1451-
if (deferralInfo != null) {
1452-
return deferralInfo.numComponents; /* Need to have this info for
1453-
ICC_ColorSpace without
1454-
causing a deferred profile
1455-
to be loaded */
1378+
ProfileDeferralInfo info = deferralInfo;
1379+
if (info != null) {
1380+
return info.numComponents;
14561381
}
14571382
theHeader = getData(icSigHead);
14581383

@@ -1536,6 +1461,24 @@ public int getNumComponents() {
15361461
return theNumComponents;
15371462
}
15381463

1464+
/**
1465+
* Returns a stream corresponding to a built-in profile
1466+
* specified by fileName.
1467+
* If there is no built-in profile with such name, then the method
1468+
* returns null.
1469+
*/
1470+
private static InputStream getStandardProfileInputStream(String fileName) {
1471+
return AccessController.doPrivileged(
1472+
new PrivilegedAction<InputStream>() {
1473+
public InputStream run () {
1474+
try {
1475+
return
1476+
new FileInputStream(getStandardProfileFile(fileName));
1477+
} catch(IOException ex) {return null;}
1478+
}
1479+
});
1480+
}
1481+
15391482

15401483
/**
15411484
* Returns a float array of length 3 containing the X, Y, and Z

0 commit comments

Comments
 (0)