JDK-4549130 : URLClassLoader: NoClassDefFoundError thrown when not using rt.jar
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.3.0,1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_7,windows_nt
  • CPU: x86,sparc
  • Submitted: 2001-12-06
  • Updated: 2006-12-06
  • Resolved: 2006-12-06
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
We are seeing a NoClassDefFoundError when we run a test case.  
We only saw this error on Solaris-sparc, not on Linux. 
I'm sort of perplexed as to why it is happening. 

I did a fresh bringover and a clean build.  I can see the classfile 
in my workspace.  The permissions are -rw-rw-rw- just like all the 
other files.  

This isn't reproducible in the promoted build: java_g -verbose:class 
shows that the class is loaded correctly.  The reason is that the 
promoted build loads classes from rt.jar.  The bug is only reproducible 
when classes are loaded from the build directory.  

We tested this using the 2D integration build for Merlin build 89.  
Dmitri built images.  When using rt.jar, the class is loaded.  When loading 
from the build directory of the same build, we get the NoClassDefFoundError.  

I've reproduced this in several builds, on different machines, dating back 
several weeks.  

/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/bin/java Test
java.lang.NoClassDefFoundError: sun/awt/datatransfer/ClipboardTransferable
        at sun.awt.datatransfer.SunClipboard.getContents(SunClipboard.java:83)
        at Test$1.run(Test.java:13)
        at java.lang.Thread.run(Thread.java:539)
echawkes@gradgrind:/home/bchristi/work/4532299( 204 )% 

Here are the last few lines from a run of java_g -verbose:class 

[Loaded java.awt.datatransfer.Transferable from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
[Loaded java.util.ListIterator from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
[Loaded java.util.LinkedList$ListItr from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
[Loaded sun.reflect.NativeMethodAccessorImpl from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
[Loaded sun.reflect.DelegatingMethodAccessorImpl from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
[Loaded sun.awt.motif.X11Selection from
/net/jano/export/disk03/awt/echawkes/jdk14-87/build/solaris-sparc/classes]
java.lang.NoClassDefFoundError: sun/awt/datatransfer/ClipboardTransferable
        at sun.awt.datatransfer.SunClipboard.getContents(SunClipboard.java:83)
        at Test$1.run(Test.java:13)
        at java.lang.Thread.run(Thread.java:539)


Test case is: 

import java.awt.Toolkit;
import java.awt.datatransfer.*;

public class Test {
    public static void main(String[] args) {
        final Object o = new Object();
        final Runnable r = new Runnable() {
                public void run() {
                    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemSelection();
                    synchronized (o) {
                        o.notifyAll();
                    }
                    Transferable t = clipboard.getContents(null);                        
                }
            };
        final Thread t = new Thread(r);
        synchronized (o) {
            t.start();
            try {
                o.wait();
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
        t.interrupt();
    }

}


Please note:  the test case above will hang if the class is loaded correctly.  
We discovered the classloader problem while trying to verify the fix for 
4532299.  The diffs that fix that hang are in the Suggested Fix section of 
4532299.  

###@###.### 2001-12-05

Update:  test works correctly when using -server -Xcomp 
NoClassDefFoundError thrown when using -client 
NoClassDefFoundError thrown when using -Xint 
 
###@###.### 2001-12-05

Comments
EVALUATION Name: dsR10078 Date: 12/06/2001 NoClassDefFoundError is thrown only if the thread is interrupted while loading the class. The bug manifestation with the test case from the bug description depends on timings. If the class gets loaded before the thread is interrupted, the bug will not manifest. This is why the bug is not reproducible with the promoted build. The problem is reproducible on both the merlin workspace and the promoted build b88 with the following minimized test case: ---------------------------------------------------------------------- public class Test { public static void main(String[] args) { final Runnable r = new Runnable() { public void run() { try { Class.forName("MyClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }; final Thread t = new Thread(r); t.start(); t.interrupt(); } } class MyClass {} ---------------------------------------------------------------------- Also it indicates the possible cause of the failure. <das@aldebaran(pts/2).353> /export2/das/b88/jre/bin/java -version java version "1.4.0-rc" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b88) Java HotSpot(TM) Client VM (build 1.4.0-rc-b88, mixed mode) <das@aldebaran(pts/2).354> /export2/das/b88/jre/bin/java Test java.lang.ClassNotFoundException: MyClass at java.net.URLClassLoader$1.run(URLClassLoader.java:198) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:189) at java.lang.ClassLoader.loadClass(ClassLoader.java:309) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:265) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:325) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:135) at Test$1.run(Test.java:6) at java.lang.Thread.run(Thread.java:539) Caused by: java.io.InterruptedIOException at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:195) at sun.misc.Resource.getBytes(Resource.java:67) at java.net.URLClassLoader.defineClass(URLClassLoader.java:246) at java.net.URLClassLoader.access$100(URLClassLoader.java:57) at java.net.URLClassLoader$1.run(URLClassLoader.java:196) ... 10 more ###@###.### 2001-12-06 ====================================================================== URLClassLoader defineClass involves FileInputStream.readBytes() which is interruptable and throws InterruptedIOException when the thread is interrupted. This problem can be removed by a proper synchronization and is definitely not a Merlin showstopper. This behavior is reproducible starting from 1.3.0. ###@###.### 2001-12-06 Name: dsR10078 Date: 12/07/2001 The resolution with proper synchronization is specific to the test case above. The root cause is that any attempt to load class on an interrupted thread fails with ClassNotFoundException or NoClassDefFoundError. The following test demonstrates another manifestation of the problem that cannot be resolved with proper synchronization: ---------------------------------------------- public class Test { public static void main(String[] args) { new HappyClass(); Thread.currentThread().interrupt(); new UnhappyClass(); } } class HappyClass {} class UnhappyClass {} ---------------------------------------------- Here is the output for merlin b88: <das@aldebaran(pts/3).282> /export2/das/b88/jre/bin/java -version java version "1.4.0-rc" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b88) Java HotSpot(TM) Client VM (build 1.4.0-rc-b88, mixed mode) <das@aldebaran(pts/3).283> /export2/das/b88/jre/bin/java Test Exception in thread "main" java.lang.NoClassDefFoundError: UnhappyClass at Test.main(Test.java:5) NoClassDefFoundError doesn't seem appropriate in this case. ###@###.### 2001-12-07 ====================================================================== On Solaris java.io is interruptible. Therefore, if you read class from a classfile and the thread gets interrupted, one gets an InterruptedIOException. One needs to catch InterruptedIOException in defineClass of URLClassLoader and then retry. For suggested fix see: http://zonked.sfbay/home/kladko/wr/clint1
11-06-2004

SUGGESTED FIX On Solaris java.io is interruptible. Therefore, if you read class from a classfile and the thread gets interrupted, one gets an InterruptedIOException. One needs to catch InterruptedIOException in defineClass of URLClassLoader and then retry. For suggested fix see: http://zonked.sfbay/home/kladko/wr/clint1
11-06-2004