JDK-6792535 : NoClassDefFoundError after failed new StreamEncoder(out, lock, Charset.defaultCh
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio.charsets
  • Affected Version: 6,6u14
  • Priority: P4
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-01-12
  • Updated: 2015-01-13
  • Resolved: 2015-01-13
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.
JDK 6
6-poolResolved
Related Reports
Relates :  
Description
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());
        }

Comments
EVALUATION Submitter tries to replace jdk/jre's default charsets repository, which is very tricky and complicated. This is not a "supported" usage.
12-01-2011