Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8287885

Local classes cause ClassLoader error if the type names are similar but not same

XMLWordPrintable

    • b16
    • x86_64
    • windows

      ADDITIONAL SYSTEM INFORMATION :
      OS = Windows 11, but I am 99% certain that this occurs for most Windows Operating systems. The relevant ones to test would be Windows 10 and Windows 8.

      $ javac --version
      javac 18

      $ java --version
      java 18 2022-03-22
      Java(TM) SE Runtime Environment (build 18+36-2087)
      Java HotSpot(TM) 64-Bit Server VM (build 18+36-2087, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      Here is a relevant StackOverflow post -- https://stackoverflow.com/q/72438283/10118965

      On Windows, if I have an ABC.java and an Abc.java in the same folder, then they are treated as the same filename, and thus, forbidden, as you cannot have duplicate filenames in the same folder. That is because Windows is case-insensitive.

      Java, on the other hand, IS case-sensitive. Therefore, ABC.java and Abc.java are considered meaningfully unique type names, and thus, are permitted.

      This causes problems when making local classes (and maybe other parts of Java too). In the attached example, I have a local enum called ABC inside of method1(), and another local enum called Abc inside of method2(). Then, I use the following command to compile the class.

      javac ClassLoaderIssue.java

      Then I use the following command to run it.

      java ClassLoaderIssue

      Which then throws the following error.

      Error: Could not find or load main class ClassLoaderIssue
      Caused by: java.lang.NoClassDefFoundError: io/github/davidalayachew/ClassLoaderIssue (wrong name: ClassLoaderIssue)

      If you look at the folder to see the generated .class files, you will see that there was only 1 of the local enums generated. On my machine, I see that only ClassLoaderIssue$1ABC.class was created, but there was no ClassLoaderIssue$1Abc.class. That is because Java treats these 2 names is unique, and therefore, is unable to create 2 different files of the same name. If I had to guess, the first local enum is created, and then the second one is created and either overwrites the first one, or silently fails to create a file.

      Regardless, the point is, this is a problem. As you can see, this is a Windows specific problem, but if I am on a Linux system (or another operating system that IS case sensitive), then this problem will not exist.

      I believe there is a very easy and simple fix here - simply increment the number when creating the local enum. Doing so should solve the problem, whether or not the underlying operating is case sensitive or case insensitive.

      So, the expected output of compiling this program should be something like the following.

      ClassLoaderIssue.class
      ClassLoaderIssue$1ABC.class
      ClassLoaderIssue$2Abc.class

      This way, we can be case sensitive regardless of the underlying operating system file name case sensitivity.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1 - Create a new folder named ClassLoaderIssue

      2 - Place the attached ClassLoaderIssue.java file into that folder

      3 - Open a command line terminal and navigate into the above folder containing the above file

      4 - Enter the following command

      javac ClassLoaderIssue.java

      5 - Look at the contents of the folder. If you are using CommandPrompt, that would be dir. If you are using a Linux system, that would be ls

      6 - Notice how there is only ClassLoaderIssue.java, and then only a single ClassLoaderIssue$1...........java file. We should expect 2 files of that format because there are 2 local enums inside of ClassLoaderIssue.java

      7 - Execute the following command

      java ClassLoaderIssue

      8 - If you are running this on Windows, you should receive the error mentioned in the description

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expected my class to run without error
      ACTUAL -
      It received the following error upon execution

      Error: Could not find or load main class ClassLoaderIssue
      Caused by: java.lang.NoClassDefFoundError: io/github/davidalayachew/ClassLoaderIssue (wrong name: ClassLoaderIssue)


      ---------- BEGIN SOURCE ----------
      /** There seems to be a class loader error when running the below method in main(). */
      public class ClassLoaderIssue
      {

         /** Method 1. */
         private void method1()
         {

            enum ABC { A, B, C, ; }
            System.out.println(ABC.A);

         }

         /** Method 2. */
         private void method2()
         {

            enum Abc { A, B, C, ; }
            System.out.println(Abc.A);

         }


         /**
          *
          * Main method.
          *
          * @param args commandline arguments that we don't care about for this example.
          *
          */
         public static void main(String[] args)
         {

            new ClassLoaderIssue().method1();

         }

      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      I could rename the enum. Regardless, this is still a problem and something that definitely needs to be fixed.

      FREQUENCY : always


            vromero Vicente Arturo Romero Zaldivar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: