JDK-4323273 : java.util.Date has a synchronization problem when initializing static vars
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:i18n
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2000-03-20
  • Updated: 2021-11-09
  • Resolved: 2000-05-05
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 Other Other
1.3.0_02 02Fixed 1.3.1Fixed 1.4.0Fixed
Related Reports
Relates :  
Relates :  
Description

Name: elC94547			Date: 03/20/2000


JDK 1.2, 1.2.2 and 1.3 class java.util.Date uses the following 
algorithm to maintain many operations like Date.getDay() etc.: 

    private final int getField(int field) {
        if (cal == null) {
            if (staticCal == null)
                makeStaticCalendars();
            synchronized (staticCal) {
                staticCal.setTimeZone(TimeZone.getDefault());
                staticCal.setTimeInMillis(fastTime);
                return staticCal.get(field);
            }
        }
        else {
            TimeZone defaultZone = TimeZone.getDefault();
            if (!defaultZone.equals(cal.getTimeZone())) {
                long ms = cal.getTimeInMillis();
                cal.setTimeZone(TimeZone.getDefault());
                cal.setTimeInMillis(ms);
            }
            return cal.get(field);
        }
    }

Here we see, that operations over the 'staticCal' are embraced 
with synchronized (staticCal) {...} section. 

But operations over the 'cal' field are not synchronized; and 
I'm afraid, that this may cause problems when the class Date 
is used by different threads. 

In particular, it looks like poor synchronization in the class 
Date is causing failures of the stress-test: 
    nsk/stress/jck12a/jck12a003
which executes hundreds of JCK 1.2a tests as concurrent threads. 
The method Date.getDay() intermittently produces an incorrect 
result in such executions. 

[ Note, that implementation of the method Date.getDay() is the 
  same in JDK 1.2, 1.2.2 and 1.3. ] 

I have observed failures of the method Date.getDay() using the  
following environment: 
- Dual Pentium-II computer, 2x350MHz, 512Mb RAM
- Windows NT 4.0 Server, SP3, IE4

To reproduce such failure, please try the script DOIT.BAT in 
the directory:
    /net/sqesvr/vsn/GammaBase/Bugs/<this_bug_number>

======================================================================
Name: elC94547			Date: 03/22/2000



I'm afraid that the description of this bug report was not enough 
clear. That was my fault -- I'm sorry! Please, let me explain the 
problem in few more details: 

Indeed: if a Date object is shared by multiple threads, 
                  ^^^^^^^^^^^^^^^^
then operations like following ought to be blocked:
 	synchronized (d) {
	    d.setYear(2000 - 1900);
	    d.setMonth(2);
	    d.setDay(21);
	    t = d.getTime();
	}

However, the test nsk/stress/jck12a/jck12a003 involve the 
JCK tests:
    lang/PKGS/pkgs015/pkgs01502/pkgs01502.html
    lang/PKGS/pkgs016/pkgs01601/pkgs01601.html
    lang/PKGS/pkgs025/pkgs02501/pkgs02501.html
    lang/PKGS/pkgs027/pkgs02701/pkgs02701.html
    lang/PKGS/pkgs027/pkgs02702/pkgs02702.html
    lang/PKGS/pkgs027/pkgs02703/pkgs02703.html
which intermittently fail on much simpler checks like e.g.: 
    Date d = new Date (96, 6, 10);  // July 10,1996
    if ( d.getDay () != 3 ) {       // Wednesday
        out.println ( "not pass 2" );
        return 2;
    }
In these checks, a Date object is NOT shared by multiple threads. 
                        ^^^^^^^^^^^^^^^^^^^^

I'm afraid, that some side effect of manipulating to static 
fileds of the class Date may prevent it from returning correct 
results when this class (not class instance!) is referenced by 
multiple threads. 

So, would you take a look at the failures of the test 
nsk/stress/jck12a/jck12a003 demonstrated by the script DOIT.BAT 
found in the directory /net/sqesvr/vsn/GammaBase/Bugs/4323273, 
please? 

The failures reproduce quite regularily -- approximately in 
3 of 10 executions. So, I believe that those failures still 
need to be investigated. 


======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: ladybird merlin-beta FIXED IN: ladybird merlin-beta INTEGRATED IN: 1.3.0_02 ladybird merlin-beta VERIFIED IN: 1.2.2_008 1.3.0_02 ladybird merlin-rc1
14-06-2004

SUGGESTED FIX *** /tmp/geta22832 Thu Mar 23 21:52:39 2000 --- Date.java Thu Mar 23 21:46:31 2000 *************** *** 1176,1184 **** cal.set(field, value); } ! private static void makeStaticCalendars() { ! staticCal = new GregorianCalendar(); ! utcCal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); ! defaultCenturyStart = staticCal.get(Calendar.YEAR) - 80; } } --- 1176,1187 ---- cal.set(field, value); } ! private synchronized static void makeStaticCalendars() { ! if (staticCal == null) { ! GregorianCalendar calendar = new GregorianCalendar(); ! utcCal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); ! defaultCenturyStart = calendar.get(Calendar.YEAR) - 80; ! staticCal = calendar; ! } } } masayoshi.okutsu@Eng 2000-03-24
24-03-2000

EVALUATION If a Date object is shared by multiple threads, an application needs to lock a Date object for a critical section. For example, if the application has the following operations, Date d; // shared by other threads long t; d.setYear(2000 - 1900); d.setMonth(2); d.setDay(21); long t = d.getTime(); All the set/get calls have to be blocked, like, Date d; // shared by other threads long t; synchronized (d) { d.setYear(2000 - 1900); d.setMonth(2); d.setDay(21); t = d.getTime(); } Synchronizing with 'cal' doesn't solve this problem. I'm closing this as not a bug. masayoshi.okutsu@Eng 2000-03-21 Reopened this bug. Date objects are not shared by threads... masayoshi.okutsu@Eng 2000-03-23 There is a critical section in makeStaticCalendars() which initializes private static variables. (The original Synopsis was confusing. The private instance variable `cal' is not involved in this bug.) masayoshi.okutsu@Eng 2000-03-23 Date.UTC() has the same problem with utcCal. This was much harder to reproduce, but it was reproduced on a 2-processor machine with 7000 threads. masayoshi.okutsu@Eng 2000-04-06
23-03-2000