JDK-6245283 : Color Management code is not thread safe in HT/SMP machine
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.3.1,1.4.1,1.4.2_01,6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,linux_redhat_3.0,solaris_8
  • CPU: generic,x86,sparc
  • Submitted: 2005-03-24
  • Updated: 2012-08-14
  • Resolved: 2005-09-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
1.4.2_10Fixed 6 b51Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
There seem thread unsafe API in java2d tech. area.

REPRODUCE :
  1) Compile the attached test case(multi.java)
  2) Launch "java multi" in HT machine or SMP machine.
     (Please try to launch several times. )
     You will see the following messages.

[guest@kronos not-thread-safe-java2d]$ java -showversion multi
java version "1.6.0-ea"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b28)
Java HotSpot(TM) Server VM (build 1.6.0-ea-b28, mixed mode)

java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at java.awt.color.ICC_ColorSpace.toRGB(ICC_ColorSpace.java:144)
        at java.awt.image.DirectColorModel.getDefaultRGBComponents(DirectColorModel.java:300)
        at java.awt.image.DirectColorModel.getRed(DirectColorModel.java:357)
        at multi.run(multi.java:25)

This issue occurs easily on HT or SMP machine.

CONFIGURATION :
  [guest@kronos not-thread-safe-java2d]$ uname -a
Linux kronos 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 i686 i686 i386 GNU/Linux

  OS : RHEL AS 3.0
  MPU : xeon 2.0[GHz] *2 (Hyper threading)
  MEM : 2GB


###@###.### 2005-03-24 01:18:36 GMT
===========================================================================================--
Customer has sent another test case.
The following is the message in 1.4.2_08 when the new test case, J100129_01_1.java.

[guest@kronos test3]$ java J100129_01_1
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)
java.awt.color.CMMException: Invalid profile data
        at sun.awt.color.CMM.checkStatus(CMM.java:127)
        at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
        at J100129_01_1.run(J100129_01_1.java:35)

Comments
EVALUATION For jdk 1.5 this bug will be fixed in update 7
20-01-2006

SUGGESTED FIX The following is suggested fix from Hitachi. Mofification has been done for 1.4.2_03 source code. ---- Suggested fix from Hitachi ---> diff -r -c -w /export1/home/tbaba/jdk/jdk1.4.2_03/solwin/j2se/src/share/classes/java/awt/color/ColorSpace.java ./rev/j2se/src/share/classes/java/awt/color/ColorSpace.java *** /export1/home/tbaba/jdk/jdk1.4.2_03/solwin/j2se/src/share/classes/java/awt/color/ColorSpace.java Tue Nov 18 11:30:40 2003 --- ./rev/j2se/src/share/classes/java/awt/color/ColorSpace.java Mon May 23 20:32:22 2005 *************** *** 81,86 **** --- 81,88 ---- static final long serialVersionUID = -409452704308689724L; + private static Object lockObj = new Object(); /**@ S200400 @**/ + /**@ S200400 @**/ private int type; private int numComponents; *************** *** 274,327 **** switch (colorspace) { case CS_sRGB: ! if (sRGBspace == null) { ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); ! sRGBspace = new ICC_ColorSpace (theProfile); ! } ! theColorSpace = sRGBspace; break; case CS_CIEXYZ: ! if (XYZspace == null) { ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_CIEXYZ); ! XYZspace = new ICC_ColorSpace (theProfile); ! } ! theColorSpace = XYZspace; break; case CS_PYCC: ! if (PYCCspace == null) { ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); ! PYCCspace = new ICC_ColorSpace (theProfile); ! } ! theColorSpace = PYCCspace; break; case CS_GRAY: ! if (GRAYspace == null) { ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); ! GRAYspace = new ICC_ColorSpace (theProfile); ! CMM.GRAYspace = GRAYspace; // to allow access from ! // java.awt.ColorModel ! } ! theColorSpace = GRAYspace; break; case CS_LINEAR_RGB: ! if (LINEAR_RGBspace == null) { ! ICC_Profile theProfile = ICC_Profile.getInstance(CS_LINEAR_RGB); ! LINEAR_RGBspace = new ICC_ColorSpace (theProfile); ! CMM.LINEAR_RGBspace = LINEAR_RGBspace; // to allow access from ! // java.awt.ColorModel ! } ! theColorSpace = LINEAR_RGBspace; break; --- 276,341 ---- switch (colorspace) { case CS_sRGB: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (sRGBspace == null) { /**@ S200400 @**/ ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); /**@ S200400 @**/ ! sRGBspace = new ICC_ColorSpace (theProfile); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! theColorSpace = sRGBspace; /**@ S200400 @**/ ! } /**@ S200400 @**/ break; case CS_CIEXYZ: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (XYZspace == null) { /**@ S200400 @**/ ! ICC_Profile theProfile /**@ S200400 @**/ ! = ICC_Profile.getInstance (CS_CIEXYZ); /**@ S200400 @**/ ! XYZspace = new ICC_ColorSpace (theProfile); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! theColorSpace = XYZspace; /**@ S200400 @**/ ! } /**@ S200400 @**/ break; case CS_PYCC: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (PYCCspace == null) { /**@ S200400 @**/ ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); /**@ S200400 @**/ ! PYCCspace = new ICC_ColorSpace (theProfile); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! theColorSpace = PYCCspace; /**@ S200400 @**/ ! } /**@ S200400 @**/ break; case CS_GRAY: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (GRAYspace == null) { /**@ S200400 @**/ ! ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); /**@ S200400 @**/ ! GRAYspace = new ICC_ColorSpace (theProfile); /**@ S200400 @**/ ! CMM.GRAYspace = GRAYspace; // to allow access from /**@ S200400 @**/ ! // java.awt.ColorModel /**@ S200400 @**/ ! } /**@ S200400 @**/ ! theColorSpace = GRAYspace; /**@ S200400 @**/ ! } /**@ S200400 @**/ break; case CS_LINEAR_RGB: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (LINEAR_RGBspace == null) { /**@ S200400 @**/ ! ICC_Profile theProfile /**@ S200400 @**/ ! = ICC_Profile.getInstance(CS_LINEAR_RGB); /**@ S200400 @**/ ! LINEAR_RGBspace = new ICC_ColorSpace (theProfile); /**@ S200400 @**/ ! CMM.LINEAR_RGBspace = LINEAR_RGBspace; // to allow access from /**@ S200400 @**/ ! // java.awt.ColorModel /**@ S200400 @**/ ! } /**@ S200400 @**/ ! theColorSpace = LINEAR_RGBspace; /**@ S200400 @**/ ! } /**@ S200400 @**/ break; diff -r -c -w /export1/home/tbaba/jdk/jdk1.4.2_03/solwin/j2se/src/share/classes/java/awt/color/ICC_Profile.java ./rev/j2se/src/share/classes/java/awt/color/ICC_Profile.java *** /export1/home/tbaba/jdk/jdk1.4.2_03/solwin/j2se/src/share/classes/java/awt/color/ICC_Profile.java Tue Nov 18 11:30:40 2003 --- ./rev/j2se/src/share/classes/java/awt/color/ICC_Profile.java Mon May 23 20:32:22 2005 *************** *** 70,75 **** --- 70,79 ---- public class ICC_Profile implements Serializable { + static final long serialVersionUID = -3938515861990936766L; /**@ S200400 @**/ + /**@ S200400 @**/ + private static Object lockObj = new Object(); /**@ S200400 @**/ + /**@ S200400 @**/ transient long ID; private transient ProfileDeferralInfo deferralInfo; *************** *** 755,799 **** try { switch (cspace) { case ColorSpace.CS_sRGB: ! if (sRGBprofile == null) { ! sRGBprofile = getDeferredInstance( ! new ProfileDeferralInfo("sRGB.pf", ColorSpace.TYPE_RGB, ! 3, CLASS_DISPLAY)); ! } ! thisProfile = sRGBprofile; break; case ColorSpace.CS_CIEXYZ: ! if (XYZprofile == null) { ! XYZprofile = getInstance ("CIEXYZ.pf"); ! } ! thisProfile = XYZprofile; break; case ColorSpace.CS_PYCC: ! if (PYCCprofile == null) { ! PYCCprofile = getInstance ("PYCC.pf"); ! } ! thisProfile = PYCCprofile; break; case ColorSpace.CS_GRAY: ! if (GRAYprofile == null) { ! GRAYprofile = getInstance ("GRAY.pf"); ! } ! thisProfile = GRAYprofile; break; case ColorSpace.CS_LINEAR_RGB: ! if (LINEAR_RGBprofile == null) { ! LINEAR_RGBprofile = getInstance ("LINEAR_RGB.pf"); ! } ! thisProfile = LINEAR_RGBprofile; break; default: --- 759,814 ---- try { switch (cspace) { case ColorSpace.CS_sRGB: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (sRGBprofile == null) { /**@ S200400 @**/ ! sRGBprofile = getDeferredInstance( /**@ S200400 @**/ ! new ProfileDeferralInfo("sRGB.pf", /**@ S200400 @**/ ! ColorSpace.TYPE_RGB, /**@ S200400 @**/ ! 3, CLASS_DISPLAY)); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! thisProfile = sRGBprofile; /**@ S200400 @**/ + } /**@ S200400 @**/ break; case ColorSpace.CS_CIEXYZ: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (XYZprofile == null) { /**@ S200400 @**/ ! XYZprofile = getInstance ("CIEXYZ.pf"); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! thisProfile = XYZprofile; /**@ S200400 @**/ + } /**@ S200400 @**/ break; case ColorSpace.CS_PYCC: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (PYCCprofile == null) { /**@ S200400 @**/ ! PYCCprofile = getInstance ("PYCC.pf"); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! thisProfile = PYCCprofile; /**@ S200400 @**/ + } /**@ S200400 @**/ break; case ColorSpace.CS_GRAY: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (GRAYprofile == null) { /**@ S200400 @**/ ! GRAYprofile = getInstance ("GRAY.pf"); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! thisProfile = GRAYprofile; /**@ S200400 @**/ + } /**@ S200400 @**/ break; case ColorSpace.CS_LINEAR_RGB: ! synchronized(lockObj) { /**@ S200400 @**/ ! if (LINEAR_RGBprofile == null) { /**@ S200400 @**/ ! LINEAR_RGBprofile = getInstance ("LINEAR_RGB.pf"); /**@ S200400 @**/ ! } /**@ S200400 @**/ ! thisProfile = LINEAR_RGBprofile; /**@ S200400 @**/ + } /**@ S200400 @**/ break; <------------------------------------ *** (#1 of 1): [ UNSAVED ] ###@###.###
28-07-2005

EVALUATION The problem is that our implementation of the singleton pattern used for managing standard color spaces and profiles (ColorSpace, ICC_Profile) is not thread safe. ###@###.### 2005-03-30 14:03:57 GMT
24-03-2005