United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6183734 : FATAL ERROR occurs when jre executes with jar file without MANIFEST in 1.4.2 on Solaris8(LANG=ja)

Submit Date:
Updated Date:
Project Name:
Resolved Date:
Affected Versions:
Fixed Versions:
1.4.2_09 (b01)

Related Reports

Sub Tasks

When a licensee executes jre with jar file without MANIFEST in LANG=ja,
FATAL ERROR and stack trace show up.

 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
        at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:27)
        at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java
        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)

  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



###@###.### 2004-12-13 17:26:33 GMT

For the testcase the work around would be to increase the SoftRefLRUPolicyMSPerMB value (default is 1000 ms).

###@###.### 2004-12-06 12:38:30 GMT

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.
- 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{
    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

Hardware and Software, Engineered to Work Together