FULL PRODUCT VERSION :
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows XP SR-2
EXTRA RELEVANT SYSTEM CONFIGURATION :
- default platform is JDK 6u11
- Run with NetBeans 6.5 using JDK 6u11
- configure platform JDK 6u03 for execution of user code
- add sources in C:\Programme\Java\jdk1.6.0_03\src\j2se\src\share\classes from jdk-6u3-fcs-src-b05-jrl-24_sep_2007.jar to platform library
- CompileOnSave enabled
A DESCRIPTION OF THE PROBLEM :
See following soure snippet from sun.nio.cs.StreamEncoder:
(https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/trunk/src/sun/nio/cs/StreamEncoder.java?rev=568&view=markup)
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock, String charsetName) throws UnsupportedEncodingException {
try {
return new StreamEncoder(out, lock, (charsetName == null) ?
Charset.defaultCharset() : Charset.forName(charsetName));
} catch (IllegalCharsetNameException icne) {
throw new UnsupportedEncodingException (icne.getCharsetName());
}
}
Running this code results in UnsatisfiedLinkError during startup of the VM, because via setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); in System.initializeSystemClass() sun.nio.cs.StreamEncoder.forOutputStreamWriter(...) is invoked, which tries to load system default charset by Charset.defaultCharset().
Charset.defaultCharset() in my project is running into code, which needs to open jar-file. The UnsatisfiedLinkError is thrown, because zip library is not loaded at this time (loadLibrary("zip"); will be invoked after setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); in System.initializeSystemClass()).
So I tried to catch this UnsatisfiedLinkError, and open new StreamEncoder by STARTUP_CHARSET, which doesn't need to load data from jar file:
try {
return new StreamEncoder(out, lock, (charsetName == null) ?
Charset.defaultCharset() : Charset.forName(charsetName));
} catch (IllegalCharsetNameException icne) {
throw new UnsupportedEncodingException (icne.getCharsetName());
} catch (Error er) { // doesn't work, file bug report
// if (sun.misc.VM.isBooted())
// throw er;
return new StreamEncoder(out, lock, STARTUP_CHARSET);
}
Running this code results in NoClassDefFoundError (see Error Message(e) section) although opening jar file isn't needed for STARTUP_CHARSET, checking sun.misc.VM.isBooted() doesn't help.
IMO this is a bug, because opening new StreamDecoder via STARTUP_CHARSET before trying it via Charset.defaultCharset() works without problems (see following source snippet).
try {
return (sun.misc.VM.isBooted() && (STARTUP_CHARSET = null) == null) // STARTUP_CHARSET is no more needed after VM is booted
? new StreamEncoder(out, lock, (charsetName == null) ?
Charset.defaultCharset() : Charset.forName(charsetName))
// workaround to avoid startup endless loop:
: new StreamEncoder(out, lock, STARTUP_CHARSET);
} catch (IllegalCharsetNameException icne) {
throw new UnsupportedEncodingException (icne.getCharsetName());
}
Failed opening new StreamEncoder via Charset.defaultCharset() seems to set system to bad unusable state, because new StreamEncoder(out, lock, STARTUP_CHARSET) in catch block (see 2nd source snippet) doesn't work anymore, which will work if invoked at first (see 3rd source snippet).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- checkout sources from (use trunk, revision 568):
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/?diff_format=s&rev=568
- Clean&Build project
- Run test sun\nio\cs\CharsetsTest.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
new StreamEncoder(out, lock, STARTUP_CHARSET) in catch block should run, too, if new StreamEncoder(out, lock, Charset.defaultCharset()) failed before.
ACTUAL -
java.lang.NoClassDefFoundError
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.NoClassDefFoundError: Could not initialize class java.util.jar.JarFile
at sun.misc.URLClassPath$JarLoader.getJarFile(URLClassPath.java:643)
at sun.misc.URLClassPath$JarLoader.access$600(URLClassPath.java:538)
at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:605)
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:597)
at sun.misc.URLClassPath$JarLoader.<init>(URLClassPath.java:581)
at sun.misc.URLClassPath$3.run(URLClassPath.java:331)
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:320)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:297)
at sun.misc.URLClassPath.getResource(URLClassPath.java:167)
at java.net.URLClassLoader$1.run(URLClassLoader.java:192)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
Exception in thread "main"
Test sun.nio.cs.CharsetsTest FAILED (crashed)
test:
BUILD SUCCESSFUL (total time: 0 seconds)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/trunk/src/sun/nio/cs/StreamEncoder.java?rev=568&view=markup
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
try {
return (sun.misc.VM.isBooted() && (STARTUP_CHARSET = null) == null) // STARTUP_CHARSET is no more needed after VM is booted
? new StreamEncoder(out, lock, (charsetName == null) ?
Charset.defaultCharset() : Charset.forName(charsetName))
// workaround to avoid startup endless loop:
: new StreamEncoder(out, lock, STARTUP_CHARSET);
} catch (IllegalCharsetNameException icne) {
throw new UnsupportedEncodingException (icne.getCharsetName());
}