Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4261469
Votes 15
Synopsis Race condition in ResourceBundle getBundle/findBundle
Category java:classes_util_i18n
Reported Against 1.0.1 , 1.2.2
Release Fixed 1.3(kestrel-beta)
State 10-Fix Delivered, bug
Priority: 4-Low
Related Bugs 4300693 , 4335714
Submit Date 10-AUG-1999
Description

A race condition in ResourceBundle - getBundle/findBundle allows
a resource to be fetched from the cacheList before getBundle finishes
establishing the resource's ancestry.

Under heavy load (many threads) an exception like this occasionally occurs:
java.util.MissingResourceException: Can't find resource for bundle java.text.resources.LocaleElements_en_US, key Eras
        at java.util.ResourceBundle.getObject(ResourceBundle.java:322)
        at java.text.DateFormatSymbols.initializeData(DateFormatSymbols.java:458)
        at java.text.DateFormatSymbols.<init>(DateFormatSymbols.java:109)
        at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:286)
        at java.util.Date.toString(Date.java:969)
        at Worker.run(Worker.java:22)


I was able to avoid the problem by modifying java.util.ResourceBundle
and synchronizing on cacheList the block of code in getBundle from the 
call to findBundle (line 412) to the end of the loop that sets the 
ancestry (line 437).  However, this approach will cause a lot of contention.
A better solution would be to modify getBundle/findBundle so a
resource is not added to the cacheList until its ancestry is complete.

This program generally reproduces the problem within five invocations.
java testDate


----testDate.java----
import java.util.*;
import java.io.*;

public class testDate {

        public static void main(String[] args) {
		synchronized (Worker.mo_lock) {
			for (int x = 0; x < 2000; x ++ ) {

				Worker w = new Worker ();
				w.start ();
			}
			//Worker.mo_lock.notifyAll ();
			System.out.println ("Beginning test");
		}
		try {
			while (true) {
				Thread.sleep (15000);
				System.out.println ("Beginning Synch sequence...");
				synchronized (Worker.mo_lock) {
					System.out.println ("Synching...");
					Worker.mb_synch = true;
					Thread.sleep (10000);
					System.gc ();
					Worker.mb_synch = false;
					int li_count = Worker.mi_numCalls;
					System.out.println ("Synching complete, " 
						+ li_count + " threads synched.");
				}
			}
		} catch (InterruptedException po) {}
	}
}
-----------------------------

----Worker.java----
import java.util.*;

        public class Worker extends Thread {
		static Object	mo_lock = new Object ();
		static public boolean  mb_synch = false;
		static public int mi_numCalls = 0;
                public Worker () {
                }
		static  void foo () {
			mi_numCalls ++;
			synchronized (mo_lock) {
				mi_numCalls = 0;
			}
		}

                public void run () {
			try {
			foo ();
				String foo;
	                        for (int y=0;y < 1000;y++) {
	                        	for (int x=0;x < 10;x++) {
       	                        	 foo = new Date ().toString ();
       		               		  }
//					System.gc ();
					if (mb_synch) foo ();

				}
			} catch (RuntimeException e) {
				e.printStackTrace ();
				System.exit (1);
//			} catch (java.lang.InterruptedException e) {
			}
                }
        }
----------------------------------
Warning:  This program spawns 2000 threads.  It can drive the
load on a 2 x Sparc 300Mhz system w/ 500MB RAM well over 30.

It's greatest chance of reproducing the test is within the first
30 seconds after printing "Beginning test."  If nothing happens
I recommend you terminate it and run it again, that should keep 
the load from getting real high.

------------------------------------
java -version:
java version "1.2.2"
HotSpot VM (1.0.1, mixed mode, build a)

java -fullversion
java full version "JDK-1.2.2-U"

------------------------------------
Modifying the exception thown in getObject at line 319 like this:
                throw new MissingResourceException("Can't find resource " 
						+ key + " in " + this.getClass().getName() 
						+ " parent = " + ((parent == null) ? "null" 
						: parent.getClass ().getName ()),
                                                   this.getClass().getName() ,
                                                   key);
	
will show that resources are indeed being used without ancestry:
java.util.MissingResourceException: Can't find resource Eras in java.text.resources.LocaleElements_en_US parent = null
        at java.util.ResourceBundle.getObject(ResourceBundle.java:320)
        at java.text.DateFormatSymbols.initializeData(DateFormatSymbols.java:458)
        at java.text.DateFormatSymbols.<init>(DateFormatSymbols.java:109)
        at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:286)
        at java.util.Date.toString(Date.java:969)
        at Worker.run(Worker.java:22)


I hope this is enough info to get the problem fixed.  Looks like it
has been around for a while (see bug# 4175900).

Currently we are seeing this in the servlet engine we are using.
It is including the current timestamp in its log file, this 
exception shows up when we do load testing (we are not in production yet)
(Review ID: 93238) 
======================================================================



There seems to be a threading/scalability problem with
HotSpot/JDK.

I have a Java server application that processes through hunderds
of thousands records an hour. It is a long running process that
performs a lot of database I/O and performs a lot of number
crunching. The program is highly threaded. There are typically
8-15 database connections open each with their own Java thread.

I am running under the following configuration:

*Solaris 5.7 - with all recommending HotSpot patches
*Sun Ultra 4 hardware - with 4 processors installed, 500M memory
*HotSport 1.0.1
The problem has occured with the default HotSpot setting and
with the following setting:
java -Xmx160m -Xconcurrentio -Xbatch

*JDK 1.2.2

Every few thousand records I get the following exception:

java.util.MissingResourceException: Can't find resource for bundle java.text.resources.LocaleElements_en, key Eras
        at java.util.ResourceBundle.getObject(ResourceBundle.java:322)
        at java.util.ResourceBundle.getObject(ResourceBundle.java:319)
        at java.text.DateFormatSymbols.initializeData(DateFormatSymbols.java:458)
        at java.text.DateFormatSymbols.<init>(DateFormatSymbols.java:109)
        at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:286)
        at com.informix.util.dateUtil.formatDate(dateUtil.java:957)
        at com.informix.util.dateUtil.getdbDateStr(dateUtil.java:409)
        at com.informix.util.dateUtil.convertDateStr(dateUtil.java:2596)
        at com.informix.jdbc.IfxDate.toString(IfxDate.java:130)
        at com.informix.jdbc.IfxResultSet.getString(IfxResultSet.java:526)
        at com.informix.jdbc.IfxResultSet.getString(IfxResultSet.java:550)
        at com.eease.lib.edbc.Query.getString(Query.java)


The problem happens consistently every few thousand records but
without any reason and at different points in the application.
The application performs a lot of Date to String conversion
in each of the many threads. The problem seems to occur more
often when the application has more threads open and processing.

This bug is causing me great pain. I am really excited about
the performance of HotSpot but this is a serious scalability
problem with the VM.

There are also a few posting the the java.lang.* news groups
where  xxxxx  people have had similar problems with this
MissingResourceException.

I look forward to hearing back from you.

Sincerely,
Sam Taha
(Review ID: 95586)

-------------------
> Hello Mark,
>
> I believe my problem is related directly to bug ID = 4261469. 
> The submitter of that bug has a similar code sample to
> yours but his loop is more intensive than yours and he says it 
> only happens 1 out of 5 times he runs his code sample.
>
> I consistently(just about every time) encounter this exception 
> when I switch my server to use threading. When I turn
> off threading and do all my database operations 
> (where the date to string conversion is being called) 
> in a serial manner I dont see the exception at all.
>
> However, I did find a way around the problem that 
> supports the existence of the bug. I reworked my code so that each
> thread creates its own java.text.SimpleDateFormat object 
> that is used during the life of the thread and used through
> out the thread for all date to string conversion. 
> With that the exception no longer happens.
>
> Hope this helps.
>
> Sam Taha

Date: Wed, 29 Sep 1999 08:14:18 -0400


Subject: Re: (Review ID: 95586) MissingResourceException in Heavily Threaded   Server

When a java.*.Date.toString() is called it creates its own new
java.text.SimpleDateFormat object that eventually calls down to the
java.util.ResourceBundle class. That is where the race condition appears to exist in the ResourceBundle class. The stack dump from my exeception shows the location. By creating a single SimpleDateFormater per thread I avoid having to call down the ResourceBundle class but once when instantiating the class.

Note that I am running my Java application on a 4 processor SUN machine and the person the reported the bug ID=4261469 was also running it on a 2 processor box.

======================================================================
Work Around

modify ResourceBundle as noted in description
======================================================================




Unknown. Someone from the news groups told me they got around it
by using a long lived SimpleDateFormat object (instead of creating
a new each time). This does not work for me since the problem
is occuring via a third party library (Informix JDBC driver).
(Review ID: 95586)
======================================================================
Evaluation
The handling of multi-threaded access to resource bundles has been totally rewritten for Kestrel, which most likely fixed this bug. Need to verify though.
 xxxxx@xxxxx  1999-08-10

Confirmed that rewrite of multi-threaded access to resource bundles fixed
this bug.

 xxxxx@xxxxx  1999-11-17
Comments
  
  Include a link with my name & email   

Submitted On 28-NOV-2000
anil_sewani
Does any one know if there is a patch that has this fix for 
1.2.2?



PLEASE NOTE: JDK6 is formerly known as Project Mustang