Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a ClassLoader exception when there are 2 objects with similar type names

I have a class with 2 methods.

  • In method1(), I create a local record called Abc. This local record is only available to method1() because it was defined in method1() (here are the rules on it according to Java).

  • In method2(), I create a local interface called ABC. Notice that there is a capitalization difference here. The local record was named Abc, but this local interface is named ABC.

Here is the class.

//package ..... //commenting out package information, as I sincerely doubt that is the cause

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

   /** Method 1. */
   private void method1()
   {
   
      record Abc(int a)
      {
      
         public static String iDontCare()
         {
         
            return "ignore this method";
         
         }
      
      }
      
      System.out.println(Abc.iDontCare()); //error
   
   }
   
   /** Method 2. */
   private void method2()
   {
   
      interface ABC
      {
      
      }
      
   }
   
 
   /**
    * 
    * Main method.
    * 
    * @param   args  commandline arguments that we don't care about for this example.
    * 
    */
   public static void main(String[] args)
   {
   
      new ClassLoaderIssue().method1();
   
   }
   
}

And here is the Exception that I get.

Exception in thread "main" java.lang.NoClassDefFoundError: ClassLoaderIssue$1ABC (wrong name: ClassLoaderIssue$1Abc)
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    at ClassLoaderIssue.method1(ClassLoaderIssue.java:23)
    at ClassLoaderIssue.main(ClassLoaderIssue.java:49)

And here is some relevant information.

Java compile command = C:\Program Files\Java\jdk-17.0.2\bin\javac.exe
Java run command = C:\Program Files\Java\jdk-17.0.2\bin\java.exe

Obviously, this is just a runnable example of the problem, but I have a situation where it is extremely convenient and helpful to have local class/enum/record to handle weird state at the very edges of my domain. Therefore, I use this pattern a lot, but this is the first time I have come across this issue.

Now obviously, there are many ways to go around this. The simplest being that I could just rename the enum for one. I already tried that and that worked. Same for the interface.

But why does this happen?

EDIT - I also tested this with Java 18 and got the same result. I used a brand new file, a brand new folder, and I copied and pasted the text (not the file), into an empty file with the same name. Same error. I can't really get a cleaner test than that.

like image 729
davidalayachew Avatar asked Dec 18 '25 15:12

davidalayachew


1 Answers

On Windows, file names are case-insensitive. This means that files called Something$ABC.class and Something$Abc.class cannot be distinguished.

Meanwhile, of course, the language itself is case-sensitive, and expects the file name and the name of the class within the file to match.

Your only recourse seems to be to rename either the class or the interface.

like image 59
dangling else Avatar answered Dec 20 '25 04:12

dangling else



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!