davidalayachew
davidalayachew

Reputation: 1553

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

I have a class with 2 methods.

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.

Upvotes: 3

Views: 2282

Answers (2)

dangling else
dangling else

Reputation: 448

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.

Upvotes: 5

TwoOfTwelve
TwoOfTwelve

Reputation: 69

I just compiled the code and ran it on my machine. It works without any problems.

Maybe try to delete all existing class files and recompile everything.

Otherwise you can try a different java version, I had similar problems related to that in the past.

Upvotes: 0

Related Questions