JDK-8024775 : ClassLoader.loadClass throws NoClassDefFoundError with similar named class
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:class_loading
  • Affected Version: 6u37
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows
  • Submitted: 2013-04-03
  • Updated: 2017-08-29
  • Resolved: 2017-08-29
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
tbd_majorResolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
>java -version
java version  " 1.6.0_37 " 
Java(TM) SE Runtime Environment (build 1.6.0_37-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Windows Server 2008 R2 Standard

A DESCRIPTION OF THE PROBLEM :
Given an existing class named 'ClassToLoad', calling classloader.loadClass( " CLASSToLoad " ) throws a NoClassDefFoundError instead of a ClassNotFoundException. [Note:the incorrect name because of caps case letters].

 This may apply on O/S that have case insensitive file naming (so the file is found but fails linking - which is case sensitive).

 I really feel this is inconsistent and breaches the 'principle of least surprise'. If I try to load a class which doesn't exist I expect a ClassNotFoundException.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please see the source add later in this form

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
If I call classloader.loadClass with the name of a class that doesn't exist, I expect a ClassNotFoundException
ACTUAL -
If I call classloader.loadClass with the name of a class that doesn't exist, but the name is similar to one that does exist (only differeing in the case some or all of the of characters) I get a NoClassDefFoundError

ERROR MESSAGES/STACK TRACES THAT OCCUR :
//
// Output from running the attached source code ...
//

Successfully loaded an existing class
Failed to load non-existent class 1 (expected behaviour)
Exception in thread  " main "  java.lang.NoClassDefFoundError: CLASSToLoad (wrong name: ClassToLoad)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at Test.main(Test.java:36)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Test {

    public static void main(String[] args) {
// normal conditions
        try {
            Test.class.getClassLoader().loadClass("ClassToLoad");
            System.out.println(" Successfully loaded an existing class ");
        } catch (ClassNotFoundException notExpected) {
// should NOT get here
            System.out.println(" Failed to load an existing class ");
            System.exit(-1);
        }


// expected failure conditions
        try {
            Test.class.getClassLoader().loadClass("NonExistingClass");
        } catch (ClassNotFoundException expected) {
            System.out.println(" Failed to load non-existent class 1 (expected behaviour) ");
        }


// inconsistent failure condition (a Bug in my opinion)
        try {
            Test.class.getClassLoader().loadClass("CLASSToLoad");
        } catch (ClassNotFoundException expected) {
            System.out.println(" Failed to load non-existent class 2 (desired behaviour) ");
        }
    }
}

//
// sample class used for the above (requires separate file)
//
public class ClassToLoad
{

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
In a generic situtation, there is no work around. In the wild, an application that performs such loading is likely to have a unbounded set of possible inputs. It would experience NoClassDefFoundErrors where it would only expect ClassNotFoundExceptions (although one might argue that any code loading foreign classes this was should defend itself against linkage errors anyway).

 I am using this is a Java program that uses reflection to check API compiance against a language and platform neutral expression of an API and therefore I have bounded input (I can treat the naming of the problematic class as a special case)
Comments
On case-insensitive file system the class loader finds and loads the classfile with requested class name. NCDFE is thrown because the binary class name is case-sensitive. The behavior is correct. If an application attempts to look up classes that may or may not exist, it should guard properly.
29-08-2017

A side case for windows class loading. Maybe this is covered in the spec already ?
13-09-2013

webbugs messed up format of test src. Attaching the Test class. Be sure to create a ClassToLoad class also (and compile both)
13-09-2013