JDK-6183734 : FATAL ERROR occurs when jre executes with jar file without MANIFEST in 1.4.2 on Solaris8(LANG=ja)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 1.4.2_02
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_8
  • CPU: sparc
  • Submitted: 2004-10-25
  • Updated: 2011-02-16
  • Resolved: 2005-04-25
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_09 b01Fixed 6Fixed
Description
When a licensee executes jre with jar file without MANIFEST in LANG=ja,
FATAL ERROR and stack trace show up.

REPORDUCE:
 1. Compile the attached a.java
 2. Launch
    java -classpath M.jar:. -Xcheck:jni -XX:SoftRefLRUPolicyMSPerMB=0 a

you will see the following message

--->
goedel[15]% java -classpath M.jar:. -Xcheck:jni -XX:SoftRefLRUPolicyMSPerMB=0 a
FATAL ERROR in native method: Static field ID passed to JNI
        at java.util.zip.ZipEntry.initFields(Native Method)
        at java.util.zip.ZipEntry.<init>(ZipEntry.java:92)
        at java.util.zip.ZipFile.getEntry(ZipFile.java:153)
        - locked <0xf1408358> (a java.util.jar.JarFile)
        at java.util.jar.JarFile.getEntry(JarFile.java:194)
        at java.util.jar.JarFile.getJarEntry(JarFile.java:181)
        at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:668)
        at sun.misc.URLClassPath$2.next(URLClassPath.java:231)
        at sun.misc.URLClassPath$2.hasMoreElements(URLClassPath.java:241)
        at java.lang.ClassLoader$2.hasMoreElements(ClassLoader.java:939)
        at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:27)
        at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java
:36)
        at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:27)
        at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java
:36)
        at sun.misc.Service$LazyIterator.hasNext(Service.java:254)
        at java.nio.charset.Charset$1.getNext(Charset.java:303)
        at java.nio.charset.Charset$1.hasNext(Charset.java:318)
        at java.nio.charset.Charset$2.run(Charset.java:361)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.nio.charset.Charset.lookupViaProviders(Charset.java:358)
        at java.nio.charset.Charset.lookup(Charset.java:385)
        at java.nio.charset.Charset.isSupported(Charset.java:407)
        at java.lang.StringCoding.lookupCharset(StringCoding.java:82)
        at java.lang.StringCoding.encode(StringCoding.java:363)
        at java.lang.StringCoding.encode(StringCoding.java:380)
        at java.lang.String.getBytes(String.java:590)
        at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
        at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:221)
        at java.io.File.exists(File.java:680)
        at java.lang.ClassLoader$3.run(ClassLoader.java:1498)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1495)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1477)
        at java.lang.Runtime.loadLibrary0(Runtime.java:788)
        - locked <0xf1b25b68> (a java.lang.Runtime)
        at java.lang.System.loadLibrary(System.java:834)
        at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:50)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.util.zip.ZipEntry.<clinit>(ZipEntry.java:45)
        at java.util.zip.ZipFile.getEntry(ZipFile.java:153)
        - locked <0xf1b299c0> (a java.util.jar.JarFile)
        at java.util.jar.JarFile.getEntry(JarFile.java:194)
        at java.util.jar.JarFile.getJarEntry(JarFile.java:181)
        at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:668)
        at sun.misc.URLClassPath.getResource(URLClassPath.java:157)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:191)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
        - locked <0xf1b28210> (a sun.misc.Launcher$AppClassLoader)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
        - locked <0xf1b28210> (a sun.misc.Launcher$AppClassLoader)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
        - locked <0xf1b28210> (a sun.misc.Launcher$AppClassLoader)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:141)
        at a.main(a.java:7)
goedel[16]%
<-----

CONFIGURATION:
  JRE : 1.4.2_02 
        java version "1.4.2_02"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
        Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)
  OS : Solaris 8(japanese)
  LANG : ja
###@###.### 10/25/04 09:03 GMT

Comments
WORK AROUND For the testcase the work around would be to increase the SoftRefLRUPolicyMSPerMB value (default is 1000 ms). ###@###.### 2004-12-06 12:38:30 GMT
25-10-2004

SUGGESTED FIX ###@###.### 2004-12-13 17:26:33 GMT
25-10-2004

EVALUATION I can reproduce the problem. It appears to *only* occur when running 1.4.2. I was not able to reproduce it with 1.5.0. (Can anyone else?) It does indeed depend on the locale of the user. I was able to reproduce it, on Solaris, with the following locales: - any EUC locale. - GBK - Hong Kong Big5 - GB18030 I could *not* reproduce it with any one-byte locale. Since this is only a pre-1.5 bug, it belongs to sustaining, but this might be a tough nut to crack. ###@###.### 10/26/04 03:15 GMT ------------------------------- Problemetic stack trace has both ZipEntry.<clinit> and ZipEntry.<init>. FATAL ERROR in native method: Static field ID passed to JNI at java.util.zip.ZipEntry.initFields(Native Method) ==> at java.util.zip.ZipEntry.<init>(Unknown Source) at java.util.zip.ZipFile.getEntry(Unknown Source) - locked <0xf1816890> (a java.util.jar.JarFile) ~~~~~~ at java.lang.System.loadLibrary(Unknown Source) at sun.security.action.LoadLibraryAction.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) ==> at java.util.zip.ZipEntry.<clinit>(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at Test6183734.main(Test6183734.java:11) Current problem has two important things to look at: 1. JVM Spec related 2. Test case related With the provided test case and the command line arguments GC is invoked with SoftRefLRUPolicyMSPerMB=0 - which means forcing all the soft reference to get collected during GC. Java system requires java.lang.StringCoding.encode() in the given environment (-Duser.language=ja_JP -Duser.country=JP). This StringCoding.encode() method is using SoftReference to store/access encoder. This SoftReference is also getting collected by the GC operation. And hence the current Encoder becomes 'null' after GC and needs to be looked-up/searched again. During lookup, the charsets.jar is being accessed and iterated to find all the available encoders. Here JarFile, ZipFile and ZipEntry are used. From the testcase, java.util.zip.ZipEntry 'class' is loaded using reflection API. During the load the 'static' initializer is being invoked by instanceKlass::initialize_impl(). In the static initializer, the dynamic library "zip" (libzip.so/zip.dll) is requested for loading. Following which the native side fields are initialized with ZipEntry.initIDs() native method. When the load libary request is being honored, the system goes and checks the available encoders down in the stack. If the encoder is available it proceeds and completes the initializer successfully. When this encoder soft reference has been GCed, system tries to get one. In the process of getting it creates the ZipEntry instance, which invokes the ZipEntry constructor. This ZipEntry(String,long) constructor calls another native method ZipEntry.initFields(), which is expected to be called only after ZipEntry.initIDs() has done the work. In instanceKlass::initialize_impl(), the 'class' object is locked only till step 6. In java an instance of this 'class' is allowed to get instantiated even with the loading status being 'being_initialized', which is not 'fully_initialized'. Thereby, the reported problem is visible only when there is some encoder is required by the system and the GC happening with SoftRefPolicy=0 ms. The same may not be reproducible with +DisableExplicitGC or SoftRefLRUPolicyMSPerMB=1000 (default). Now, to solve the issue: 1. Is it allowed to create a new instance from within the object's static initializer ? JVM spec is not clear in that, but does mention about 'Synchronize on the Class object that represents the class or interface to be initialized.' A test with the following code works well: class A{ static{ System.out.println( "<clinit>{" ); A a = new A(); System.out.println( "<clinit>}" ); } public A(){ System.out.println( "<init>" ); } } 2. SoftReference collection is working as expected and hence the affected code may not require any modification. So the static block code to initialize the native side field IDs have to be moved to constructor and a condition to validate one time initialization. ###@###.### 2004-12-06 12:38:30 GMT Please try out my untested Suggested Fix. ###@###.### 2004-12-12 03:47:53 GMT
25-10-2004