为什么当有2个类型名称相似的对象时会出现ClassLoader异常
Why is there a ClassLoader exception when there are 2 objects with similar type names
我有一个 class 有 2 种方法。
在 method1()
中,我创建了一个名为 Abc
的 local record
。此 local record
仅适用于 method1()
,因为它是 在 method1()
中定义的(here are the rules on it according to Java).
在 method2()
中,我创建了一个名为 ABC
的 local interface
。请注意,此处存在大小写差异。 local record
被命名为 Abc
,但是这个 local interface
被命名为 ABC
。
这里是 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();
}
}
这是我得到的异常。
Exception in thread "main" java.lang.NoClassDefFoundError: ClassLoaderIssueABC (wrong name: ClassLoaderIssueAbc)
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)
这里是一些相关信息。
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
显然,这只是问题的一个可运行示例,但在我的情况下,让 local class/enum/record
处理域边缘的奇怪状态非常方便和有帮助。因此,我经常使用这种模式,但这是我第一次遇到这个问题。
显然,有很多方法可以解决这个问题。最简单的是我可以为一个枚举重命名。我已经尝试过并且有效。界面相同。
但是为什么会这样呢?
EDIT - 我还用 Java 18 测试了这个并得到了相同的结果。我使用了一个全新的文件,一个全新的文件夹,然后将文本(不是文件)复制并粘贴到一个同名的空文件中。同样的错误。我真的找不到比这更干净的测试了。
我刚刚编译了代码并 运行 它在我的机器上。它没有任何问题。
也许尝试删除所有现有 class 文件并重新编译所有内容。
否则你可以尝试不同的 java 版本,我过去也遇到过类似的问题。
在 Windows 上,文件名为 case-insensitive。这意味着无法区分名为 Something$ABC.class 和 Something$Abc.class 的文件。
同时,当然,语言本身是 case-sensitive,并期望文件名和文件中 class 的名称相匹配。
您唯一的办法似乎是重命名 class 或界面。
我有一个 class 有 2 种方法。
在
method1()
中,我创建了一个名为Abc
的local record
。此local record
仅适用于method1()
,因为它是 在method1()
中定义的(here are the rules on it according to Java).在
method2()
中,我创建了一个名为ABC
的local interface
。请注意,此处存在大小写差异。local record
被命名为Abc
,但是这个local interface
被命名为ABC
。
这里是 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();
}
}
这是我得到的异常。
Exception in thread "main" java.lang.NoClassDefFoundError: ClassLoaderIssueABC (wrong name: ClassLoaderIssueAbc)
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)
这里是一些相关信息。
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
显然,这只是问题的一个可运行示例,但在我的情况下,让 local class/enum/record
处理域边缘的奇怪状态非常方便和有帮助。因此,我经常使用这种模式,但这是我第一次遇到这个问题。
显然,有很多方法可以解决这个问题。最简单的是我可以为一个枚举重命名。我已经尝试过并且有效。界面相同。
但是为什么会这样呢?
EDIT - 我还用 Java 18 测试了这个并得到了相同的结果。我使用了一个全新的文件,一个全新的文件夹,然后将文本(不是文件)复制并粘贴到一个同名的空文件中。同样的错误。我真的找不到比这更干净的测试了。
我刚刚编译了代码并 运行 它在我的机器上。它没有任何问题。
也许尝试删除所有现有 class 文件并重新编译所有内容。
否则你可以尝试不同的 java 版本,我过去也遇到过类似的问题。
在 Windows 上,文件名为 case-insensitive。这意味着无法区分名为 Something$ABC.class 和 Something$Abc.class 的文件。
同时,当然,语言本身是 case-sensitive,并期望文件名和文件中 class 的名称相匹配。
您唯一的办法似乎是重命名 class 或界面。