Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NoSuchFieldErrorJava_Java_Debugging - Fatal编程技术网

NoSuchFieldErrorJava

NoSuchFieldErrorJava,java,debugging,Java,Debugging,我的代码中出现了一个NoSuchFieldError,现在oracle不太清楚抛出此错误的原因,只是说:只有在类的定义发生不兼容的更改时,此错误才能在运行时发生 有人能向我解释一下,一个人如何能“不兼容地改变”一个班级吗?我所说的类扩展了相当多的类,因此我怀疑这可能与此有关,但我不知道从何处开始查找,也不知道我在查找什么。这意味着您可能已重新编译了另一个已编译类所依赖的类,而没有重新编译依赖的类 例如: public class MyClass { public int num;

我的代码中出现了一个NoSuchFieldError,现在oracle不太清楚抛出此错误的原因,只是说:只有在类的定义发生不兼容的更改时,此错误才能在运行时发生


有人能向我解释一下,一个人如何能“不兼容地改变”一个班级吗?我所说的类扩展了相当多的类,因此我怀疑这可能与此有关,但我不知道从何处开始查找,也不知道我在查找什么。

这意味着您可能已重新编译了另一个已编译类所依赖的类,而没有重新编译依赖的类

例如:

public class MyClass {
    public int num;
    public MyClass() { num = 1; }
}

public class MyDependingClass {
    private int foo;
    public MyDependingClass(MyClass init) {
        foo = init.num;
    }
}
因此,您可以手动重新编译这两个类(IDE通常会为您更新项目工作区,以便处理不同的类)

它成功了

稍后,您决定重构MyClass:

public class MyClass {
    private int innernum;
    public int getNum() {
        return innernum;
    }
    public MyClass() { innernum = 1; }
}
如果编译MyClass而不是MyDependingClass,则在运行程序并创建MyDependingClass实例时,将出现NoSuchFieldError

短期修复方法可能是重新编译工作区中的所有类,这将显示错误


长期的解决办法是使用Eclipse或NetBeans或其他IDE来为您处理此问题。

如果您只是部分重新编译代码,通常会抛出此错误。您的旧代码引用了重新编译的类文件中不再存在的字段

解决方案是清除所有类文件,并从fresh编译所有内容

更新:如果在重新编译所有内容后仍然出现相同的错误,则可能是针对外部库的一个版本进行编译,并在运行时使用另一个版本


您现在需要做的是首先确定导致问题的类(看起来您已经这样做了),然后使用
-verbose:class
命令行选项运行应用程序。它将在您的标准输出上转储大量类加载信息,您将能够找到问题类的确切加载位置

当编译器编译抛出错误的代码时,另一个类有一个字段,您的类可以访问该字段(读取或更改值)

在运行时,另一个类不知何故没有具有此名称的字段,这导致了上述错误

一个原因可能是第二个类在没有重新编译第一个类的情况下发生了更改。 重新编译您的所有类,您应该得到一个编译器错误(这将为您提供有关如何解决此问题的更多信息),或者该类将引用正确的类


另一个原因可能是您在类路径(不同版本)中的多个jar文件(或目录)中有某个类,导致其他一些类使用了错误的类。检查重复类上的所有JAR。

在IDE中跟踪这些错误(我的例子中是Eclipse)时需要注意的一点是观察项目可能依赖的项目的依赖关系。如果在不同的依赖项目中使用不同版本的库,则类路径加载程序可能会选择错误的库。这包括一个依赖于从Eclipse项目创建的jar的项目,以及另一个依赖于该项目和生成jar的项目的项目。jar中过时的类可能会被加载,而不是从项目中加载类

示例:

project1
取决于
project2
project3

project3
依赖于
project2.jar
,它是从
project2

最后一个静态字段被添加到重新编译的
project2
中的类中, 而不重建
project2.jar


运行
project1
可能会导致异常,因为
project2
中的类可能直接从项目或jar加载,而jar没有字段

这对我来说相当棘手,所以我正在编写解决方案

我在IntelliJ中使用Boot,一切都很好,所有Java8版本都进行了适当的设置

几个小时后,我不知何故在终端上检查了javac-version,猜猜看,它被设置为版本9。所以一定要寻找javac,我知道它是违反直觉的,但据推测,因为我已经在bash profile、IntelliJ等上设置了jdk,所以我不必为它操心


希望有帮助

理解此错误:

这是一个
java.lang.LinkageError
错误,当jvm尝试链接加载的类时会发生此错误。请注意,首先编译代码(使用依赖类),然后jvm加载所有涉及的类,然后将这些类链接在一起

考虑一下错误:
NoSuchField
,这意味着链接目标类时,字段不在那里。但是在编译时,类应该具有该字段,否则代码无法编译。链接时,jvm发现该字段不存在。所以唯一的原因是我们正在使用一个带有该字段的类进行编译,并且该类的另一个版本(没有该字段)被加载并链接。


在导致此错误的两个常见原因之间确定您的情况

通常错误加载的类要么是您修改过的源代码,要么是某个依赖jar包中的类。我们可以通过向试图在ide中运行应用程序的jvm添加
-verbose:class
参数来查找错误加载的类来确定这一点。此参数打印控制台中所有加载的类。在eclipse中,我们将其放置在:右键单击您的项目->运行方式->运行配置->参数
标记->虚拟机参数
字段

在发现错误加载的类之后,通常是