JDK-4346857 : javac should warn about case insensitive type conflicts
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_98,windows_nt
  • CPU: x86
  • Submitted: 2000-06-20
  • Updated: 2001-03-06
  • Resolved: 2001-03-06
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
Name: skT45625			Date: 06/20/2000


/*
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Server VM (build 2.0fcs-E, mixed mode)

I can compile the following code using javac or jikes, but I couldn't get it
run.  It throws me NoClassDefFoundError.  I guess because I use class Flow and
flow -- but class name suppose to be case sensitive.  If I change flow to
flow1, it works.


*/
public class Flow {
    public Flow () {
        System.out.println("Default Constructor");
    }

    public Flow (int a) {
        System.out.println("a = " + a);
    }

    public void test() {
        System.out.println("Testing Now");
    }

    public static void main(String args[]) {
        Flow f = new flow();
        if (f instanceof java.io.Serializable)
            System.out.println("Serializable");
        if (f instanceof Cloneable)
            System.out.println("Cloneable");
        f.test();
    }
}

class flow extends Flow implements Cloneable {
    public flow () {
//              super ();
        System.out.println("Cloneable");
    }
}

class Flow2 extends flow implements java.io.Serializable {
    public Flow2 (int a) {
        System.out.println("a2 = " + a);
    }
}

###@###.###  2000-06-20
reproducable on WinNT but not on sparc.
(Review ID: 106329) 
======================================================================

Name: tb29552			Date: 03/03/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

======================================================================
 (Synopsis: javac should warn about case insensitive type conflicts)

On Windows, and other case insensitive platforms, javac should
give a fatal compilation error when two classes generate the same
filename case insensitively.  Currently, it just silently
overwrites the first version of the .class file with the new
version with different capitalization, breaking code.  And, in
light of bug 4376513, where the virtual machine kills the
executing thread with a non-trappable error when a .class binary
records a different case than the filename, the results are even
more drastic.

For example, compile and try to run this program on a Windows machine:
class A {
  static class Foo {}
  static class fOO {}
  public static void main(String[] args) {
    System.out.println(new Foo());
    System.out.println(new fOO());
  }
}

Only two files are generated (A.class, A$Foo.class), and the contents of
A$Foo.class is the binary representation of A.fOO.  The generated error during
execution is non-trappable:

Exception in thread "main" java.lang.NoClassDefFoundError: A$Foo (wrong name:
A$fOO)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:486)
        at
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:111)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:248)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:297)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:286)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
        at A.main(A.java:5)

Notice that since Windows is case insensitive, it is already impossible to name
two top-level .java files with a clash.  Likewise, local and anonymous classes
are uniquified by the compiler, and should never clash (although this is not
100% true since users can include $ in identifiers, but that is another story).
 Therefore, the problem is limited in scope to nested and inner
classes.

(Review ID: 118040) 

Comments
WORK AROUND Name: skT45625 Date: 06/20/2000 change the class name from flow to flow1 ====================================================================== Name: tb29552 Date: 03/03/2001 By following the recommended naming conventions, the above example would never be written to cause a problem (fOO is not a typical class name). However, in real code, it takes developer caution to make sure there are not clashes, such as Datagram and DataGram, defined in the same package. This is important even for developers in Unix and other (true) OS's, since code which works on those platforms in spite of case insensitive conflicts is non-portable. (Review ID: 118040) ======================================================================
11-06-2004

PUBLIC COMMENTS .
10-06-2004

EVALUATION This needs a comprehensive solution in the form of a specification of the mapping from class name to file name. Currenly that specification is vaporware and the compiler makes some poor choices, such as reusing the same file for different classes. This bug cannot be fixed without such a specification. See 4421728. neal.gafter@Eng 2001-03-06
06-03-2001