Java“NoSuchMethodError”
我越来越:
NoSuchMethodError: com.foo.SomeService.doSmth()Z
我是否正确理解这个'Z'
意味着doSmth()方法的返回类型是布尔值? 如果为true,那么这种方法确实不存在,因为此方法返回一些Collection。 但另一方面,如果我调用此方法,我不会将其返回值赋给任何变量。 我只是这样调用这个方法:
service.doSmth();
有什么想法发生这个错误? 存在所有必需的JAR文件,并且此类中的所有其他方法似乎都存在。
看起来在编译期间类路径中存在方法,但在应用程序运行期间不存在。
我不认为返回类型是一个问题。 如果是的话,就不会编译。 当方法调用不明确时编译器抛出错误,并且当两个方法仅由返回类型不同时。
通常,编译器会捕获此错误; 如果类的定义不兼容地更改,则此错误只能在运行时发生。
简而言之 – 运行时的类/ jar文件与您在编译时使用的文件不同。
这可能是您的编译时类路径和运行时类路径之间的差异。
这是似乎正在发生的事情:
- 代码使用类路径编译,该路径定义返回布尔值的
doSmth()
方法。 字节码指的是doSmth()Z
方法。 - 在运行时,
doSmth()Z
方法。 找到返回Collection的方法。
要解决此问题,请检查(编译时)类路径。
目前的回复只是告诉你为什么失败。 通常更了解如何解决问题。 如上所述,问题通常是您构建了程序,但在运行或导出程序时,不包含库。 所以解决方案是……
如果您正在运行,请检查运行配置选择运行选项卡 – >运行配置 – >选择您正在运行的配置 – >检查类路径选项卡 – >确保您需要的库在那里
如果要导出(例如war文件),请按照此选择项目 – >选择属性 – >选择部署程序集 – >按添加 – >选择Java构建路径条目 – >选择要包含在导出文件中的库(例如战争文件)
在这两种情况下,请确保包含您引用的库。
此错误的其他常见问题不是正确的参数类型或可见性,但编译器将在运行之前检测到错误。 在这种情况下,只需检查文档以匹配函数和包可见性,并确保在项目属性中的Java Build Path中找到该库。
也许仍然可以帮助某人,但是当你在类路径上有两个具有相同确切签名但不具有相同公共方法的jar文件中的类时,也会发生这种exception。
例如:
-
在文件mylibrary1.jar上有com.mypackage.mysubpackage.MyClass类,方法是doSmth()
-
在文件mylibrary2.jar上你有com.mypackage.mysubpackage.MyClass类没有方法doSmth()
在搜索类时,类加载器可能会找到第一个mylibrary2.jar,具体取决于路径优先级,但无法在该类上找到该方法。
确保在两个不同的文件上没有相同的包+类。
我注意到在Eclipse中从SVN更新它们时,在测试多个链接项目中的一些实验性更改时发生了这个问题。
具体来说,我更新了SVN中的所有项目,并还原了.classpath文件,而不是手动编辑它以保持简单。
然后我将链接的项目重新添加到路径中,但忘记删除相关的jar。 这就是我遇到问题的方式。
显然,运行时使用jar文件,而编译器使用项目文件。
另一种可能发生的方式很难找到:
如果外部jar中方法的签名发生更改,导致IDE中没有发现错误,因为它仍然与您调用它的方式兼容,则可能无法重新编译该类。
如果构建检查文件是否有更改,然后只重新编译它们,则在构建过程中可能不会重新编译该类。
所以当你运行它时可能会导致这个问题。 虽然你有新的jar,你自己的代码仍然需要旧代码,但绝不会抱怨。
为了使它变得更难,它取决于jvm是否可以处理这种情况。 因此,在最坏的情况下,它在测试服务器上运行,但不在实时机器上运行。