United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6941137 : DST broken when jre/lib/zi is moved elsewhere and replaced with symlink.

Details
Type:
Bug
Submit Date:
2010-04-06
Status:
Closed
Updated Date:
2011-03-07
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
core-libs
OS:
linux_ubuntu
Sub-Component:
java.util:i18n
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6u18
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:

Sub Tasks

Description
FULL PRODUCT VERSION :
$ ./jdk1.6.0_18/bin/java -version
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux vm23.example.com 2.6.31-17-generic #54-Ubuntu SMP Thu Dec 10 16:20:31 UTC 2009 i686 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
We maintain a central master copy of the Olsen ZI database, to which all our installed JVMs refer. So when a new JVM is installed, its lib/zi directory is replaced with a symlink to the master ZI database. This has worked fine for every Sun JVM except 1.6.0_18, which fails if the target of the lib/zi symlink is anywhere except in the lib directory itself. See below for details of how to reproduce.

  Interestingly, the reproduction below includes slf4j (http://www.slf4j.org) and logback (http://logback.qos.ch), but I can see the same problem with other logging frameworks. Perhaps there is some nontrivial bit of date processing typically done by logging frameworks which triggers this. I was not able to isolate the issue further.


I propose the following patch to sun.util.calendar.ZoneInfoFile, which fixes 
the issue.

--- ZoneInfoFile.java.orig	2010-04-13 17:00:24.098498207 +0100
+++ ZoneInfoFile.java	2010-04-13 19:32:10.000000000 +0100
@@ -457,13 +457,13 @@
     private static final String ziDir;
     static {
         ziDir = (String) AccessController.doPrivileged(new 
PrivilegedAction() {
 		    public Object run() {
 			String zi = System.getProperty("java.home") +
-			    File.separator + "lib" + File.separator + "zi";
+			    File.separator + "lib" + File.separator + "zi" + File.separator + 
"ZoneInfoMappings";
 			try {
-			    zi = new File(zi).getCanonicalPath();
+			    zi = new File(zi).getCanonicalFile().getParent();
 			} catch(Exception e) {
 			}
 		    return zi;
 	    	    } });
     }

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ uname -a
Linux vm23.example.com 2.6.31-17-generic #54-Ubuntu SMP Thu Dec 10 16:20:31 UTC 2009 i686 GNU/Linux
$ pwd
/var/tmp/j6u18
$ ls
jdk-6u18-linux-i586.bin  logback-0.9.19.tar.gz  slf4j-1.5.11.tar.gz
$ bash ./jdk-6u18-linux-i586.bin
:
Done.
$ gunzip -c slf4j-1.5.11.tar.gz | tar xf -
$ gunzip -c logback-0.9.19.tar.gz | tar xf -
$ ls
jdk1.6.0_18  jdk-6u18-linux-i586.bin  logback-0.9.19  logback-0.9.19.tar.gz  slf4j-1.5.11  slf4j-1.5.11.tar.gz
$ export CLASSPATH=/var/tmp/j6u18/logback-0.9.19/logback-classic-0.9.19.jar:/var/tmp/j6u18/logback-0.9.19/logback-core-0.9.19.jar:/var/tmp/j6u18/slf4j-1.5.11/slf4j-api-1.5.11.jar:.
$ cat > Main.java <<EOF
> import java.util.Date;
> import java.util.Calendar;
> import java.text.SimpleDateFormat;
> import org.slf4j.Logger;
> import org.slf4j.LoggerFactory;
> public class Main {
>     public static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
>     public static void main(String[] args) {
>         SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss MMM dd yyyy Z zzzz");
>         sdf.setCalendar(Calendar.getInstance());
>         LOGGER.info("Local: " + sdf.format(new Date()));
>     }
> }
> EOF
$ jdk1.6.0_18/bin/javac Main.java
$ date --utc
Tue Mar 30 15:14:06 UTC 2010
$ TZ=US/Eastern jdk1.6.0_18/bin/java Main
11:14:49.443 [main] INFO  Main - Local: 11:14:49 Mar 30 2010 -0400 Eastern Daylight Time
$ cd jdk1.6.0_18/jre/lib/
$ rm -rf /var/tmp/zi
$ mv zi /var/tmp/
$ ln -s /var/tmp/zi zi
$ cd ../../../
$ TZ=US/Eastern jdk1.6.0_18/bin/java Main
10:15:42.527 [main] INFO  Main - Local: 10:15:42 Mar 30 2010 -0500 GMT-05:00
$ 


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I was expecting the second run to yield a time zone of "-0400 Eastern Daylight Time".
ACTUAL -
A timezone of "-0500 GMT-05:00", which is incorrect now that the US is in DST.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
See "Steps to Reproduce"
---------- END SOURCE ----------

Release Regression From : 6u17
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

                                    

Comments
EVALUATION

Fixed with NIO2 API for JDK7.
                                     
2010-09-10
EVALUATION

It's a java.io problem, but we will use a workaround fix in the time zone code.
                                     
2010-08-16
WORK AROUND

Disabling the canonicalization cache removes the problem:

-Dsun.io.useCanonCaches=false -Dsun.io.useCanonPrefixCache=false

However, it will affect runtime performance.
                                     
2010-04-07
EVALUATION

sun.util.calendar.ZoneInfoFile was changed to call File.getCanonicalPath for fixing 6824265. There seems to be a canonicalization problem with its cache when the logging libraries are used. Transferring this CR to classes_io.
                                     
2010-04-07



Hardware and Software, Engineered to Work Together