debugging 无此类字段错误Java

vfh0ocws  于 2022-11-14  发布在  Java
关注(0)|答案(8)|浏览(120)

我的代码中出现NoSuchFieldError,现在oracle不太清楚为什么会抛出此错误,只是说:* 如果类的定义发生了不兼容的更改,则此错误只会在运行时发生。*
有人能给我解释一下如何“不兼容地改变”一个类吗?我正在谈论的类扩展了相当多的类,所以我怀疑它可能与此有关,但我不知道从哪里开始寻找或我在寻找什么。

70gysomp

70gysomp1#

如果您只重新编译部分代码,通常会抛出此错误。您的旧代码引用了重新编译的类文件中不再存在的字段。
解决方案是清除所有类文件,并重新编译所有内容。

**更新:**如果在重新编译所有内容后仍然得到相同的错误,那么您可能是在编译外部库的一个版本,而在运行时使用另一个版本。

你现在需要做的是首先识别出导致问题的类(看起来你已经做了这件事),然后用-verbose:class命令行选项运行你的应用程序。它会在你的标准输出上转储大量的类加载信息,你将能够找到有问题的类是从哪里加载的。

rqcrx0a6

rqcrx0a62#

当编译器编译掷回错误的程式码时,有其他具有字段的类别,而您的类别可以存取这个字段(阅读或变更值)。
在运行时,另一个类不知何故没有具有此名称的字段,这导致了上述错误。
一个原因可能是第二个类在没有重新编译第一个类的情况下发生了变化。重新编译所有的类,你应该得到一个编译器错误(这将给予你更多关于如何解决这个问题的信息),或者类将引用正确的类。
另一个原因可能是您在类路径中的多个jar文件(或目录)中有某个类(在不同的版本中),导致其他一些类使用了错误的类。请检查所有jar中的重复类。

xzv2uavs

xzv2uavs3#

在IDE中跟踪这些错误时需要注意的事项如果在不同的依赖项目中使用不同版本的库,类路径加载器可能会选择错误的版本,这包括让一个项目依赖于一个从Eclipse项目创建的jar,并且具有依赖于该项目和从其生成JAR的项目的另一项目。JAR中的过时类可能被潜在地加载,而不是来自该项目的类。

范例:

project1依赖于project2project3
project3依赖于project2.jarproject2.jar是从project2中的类文件生成的jar
将final静态字段添加到project2中的类,并重新编译该类,而不重新生成project2.jar
运行project1可能会导致异常,因为project2中的类可能直接从项目或jar(没有字段)中加载

qnyhuwrf

qnyhuwrf4#

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

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来处理此问题。

92vpleto

92vpleto5#

虽然根本原因与前面的答案中描述的相同,但我的问题与我在这里找到的其他答案有点不同,所以我想我应该分享一下。
我正在处理一个大型项目,其中有几个maven pom分布在整个项目中。一位同事更新了其中一个依赖项的版本号,但没有更新该依赖项出现的每个位置,导致类路径上的库不匹配。
解决方案是更新此依赖项的每次出现,使其具有相同的版本号。作为补充说明,为了防止这种情况再次发生,我们在此处添加了一个变量,现在我们从一个位置控制这些依赖项的版本号。

voase2hg

voase2hg6#

这对我来说相当棘手,所以我正在写我的解决方案。
我在IntelliJ中工作,启动一切正常,所有Java 8版本都设置正确。
几个小时后,我不知何故在终端上检查了javac -version,你猜怎么着,它被设置为版本9。所以一定要查找javac,我知道这是违反直觉的,但据推测,因为我已经在bash配置文件、IntelliJ等上设置了jdk,所以我不应该为此而烦恼。
希望能有所帮助!

knpiaxh1

knpiaxh17#

了解此错误:

这是一个java.lang.LinkageError错误,发生在jvm试图链接已加载的类时。注意,代码首先被编译(带有依赖类),然后所有涉及的类都被jvm加载,然后这些类被链接在一起。
思考错误:NoSuchField,这意味着当链接目标类时,该字段不存在。但是当编译时,类应该具有该字段,否则代码无法编译。当链接时,JVM发现该字段不存在。所以唯一的原因是我们正在编译具有该字段的类,并且加载并链接了该类的另一个版本(不具有该字段)。

请在此错误的两个常见原因之间选择您的情况

通常,错误加载的类要么是您修改的源代码,要么是您依赖的jar包中的一个类。我们可以通过在IDE中试图运行您的应用程序的jvm中添加-verbose:class参数来找到错误加载的类来确定这一点。该参数在控制台中打印所有加载的类。在eclipse中,我们将其放置在:右键单击项目-〉运行方式-〉运行配置-〉arguments标记-〉VM argument字段。
当你发现错误加载的类后,通常它要么是你的项目中有源代码的类,要么是你的项目依赖的jar包中的类,不同的情况导致不同的解决方案。

源代码案例的解决方案:

很有可能您更改了该类(在源代码中添加了字段),但没有重新编译它。这可能是由于不同的原因,但您应该删除旧版本编译的该类的.class文件,并重新编译它,让新版本的.class文件包含该字段。

罐 Package 箱解决方案:

你应该试着让项目加载正确的jar包。但是为什么不同的版本会被包含,通常是因为它们都依赖于(你项目的不同部分)。情况很简单(可能在真实的世界的项目中不存在),如果你写的代码直接依赖于它们,只需要选择一个,然后丢弃另一个。
但是很可能你的代码间接地依赖于它们,你不想改变你的代码(或者尽可能少地改变)。
一种解决方案是编写自己的ClassLoader来处理这两种情况:Possible to use two java classes with same name and same package?(我没有尝试)
如果你选择加载正确的版本(包含这样的field),并且你的代码间接依赖于wrong版本仍然可以工作(希望如此),那么我们有一个简单得多的解决方案:让项目选择正确的版本。
以eclipse为例,你可以在你的Java Build Path属性中使用Order and Export标签,只是调整顺序,让正确的版本在wrong版本之前,因为Order部分的函数是:
一方面,它的作用是解决在构建所讨论的项目中使用的资源的顺序(“顺序”部分)。
如果正确的版本或错误的版本没有出现在那里,你应该确定哪个包依赖于它,并调整它的顺序,由于Export部分的功能。阅读The "Order and Export" tab in "Java Build Path"了解详情。

jum4pzuy

jum4pzuy8#

我在尝试添加Kotlin版本大于项目的Gradle插件时遇到java.lang.NoSuchFieldError: KOTLIN_STAT_LABEl_PROPERTY异常。因此,降低插件的kotlin版本或升级项目的kotlin版本可能会解决此问题。

相关问题