United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6245283 : Color Management code is not thread safe in HT/SMP machine

Details
Type:
Bug
Submit Date:
2005-03-24
Status:
Resolved
Updated Date:
2012-08-14
Project Name:
JDK
Resolved Date:
2005-09-06
Component:
client-libs
OS:
solaris_8,linux_redhat_3.0,generic
Sub-Component:
2d
CPU:
x86,sparc,generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.3.1,1.4.1,1.4.2_01,6
Fixed Versions:

Related Reports
Backport:
Backport:
Duplicate:
Duplicate:
Relates:

Sub Tasks

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
                                     
2006-01-20
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 ] ###@###.###
                                     
2005-07-28
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
                                     
2005-03-24



Hardware and Software, Engineered to Work Together