简体   繁体   English

类路径问题

[英]Classpath Issue

I am trying to run a map/reduce job and I am getting a java.lang.NoSuchMethodError. 我正在尝试运行地图/缩小作业,并且遇到了java.lang.NoSuchMethodError。 I did some research on this and this appears when my code is executed (not compiled). 我对此进行了一些研究,这在我的代码执行(未编译)时出现。 The correct version of the class and methods are there during compilation, but when trying to run, the correct method is not available. 正确的类和方法版本在编译期间存在,但是在尝试运行时,正确的方法不可用。 The jar file that is causing this is guava. 导致此问题的jar文件是番石榴。 I know this from the stack that is printed. 我从打印的堆栈中知道这一点。 I throws an error when trying to execute the following line of code: 尝试执行以下代码行时抛出错误:

ArrayDeque<Entry<String, String>> a = Queues.newArrayDeque();

This jar is part of the hadoop classpath because it comes with the CDH verson 5.3.0 that I am using. 这个jar是hadoop类路径的一部分,因为它与我正在使用的CDH版本5.3.0一起提供。 I have tried adding the correct version of guava to the classpath, but the error does not change. 我尝试将正确版本的番石榴添加到类路径中,但是错误不会改变。 My questions are as follows: 我的问题如下:

  1. I believe that I have correctly identified the issue. 我相信我已经正确识别了问题。 Does this seem reasonable to you? 您觉得这合理吗? I have never come across this error before. 我以前从未遇到过这个错误。

  2. I believe that I need to remove the older version of guava from the classpath and add the new one. 我相信我需要从类路径中删除旧版本的番石榴并添加新版本。 However, I really do not know where to begin with correcting this. 但是,我真的不知道从哪里开始纠正此问题。 The command that is issued to hadoop jar does not contain the older version of guava (in the -libjar parm). 发出给hadoop jar的命令不包含旧版本的guava(在-libjar parm中)。 The jar is part of the hadoop classpath when I issue the command "hadoop classpath". 当我发出命令“ hadoop classpath”时,jar是hadoop classpath的一部分。 So I am assuming that there is some hadoop config file I could edit to make this go away. 因此,我假设我可以编辑一些hadoop配置文件来使它消失。 Is that the correct way to go, or is there some other thing I need to do? 这是正确的方法吗,还是我需要做其他事情?

I am using Java 7, CDH 5.3.0, NetBeans 8. 我正在使用Java 7,CDH 5.3.0,NetBeans 8。

TIA TIA

At the time that I'm writing this, Hadoop has a dependency on Guava version 11.0.2. 在撰写本文时,Hadoop依赖于Guava版本11.0.2。 It uses the library pretty heavily in its internal implementation. 它在其内部实现中大量使用该库。

According to the Guava JavaDocs, the Queues#newArrayDeque method was added in version 12.0. 根据Guava JavaDocs,在版本12.0中添加了Queues#newArrayDeque方法。 If your code is compiling successfully, then that means that Guava version 12.0 or higher is available on your compilation classpath at build time, but since version 11.0.2 is supplied at runtime by Hadoop, the method doesn't exist, resulting in NoSuchMethodError . 如果您的代码编译成功,则意味着在构建时可在编译类路径上使用Guava 12.0或更高版本,但是由于Hadoop在运行时提供了11.0.2版,因此该方法不存在,从而导致NoSuchMethodError

Unfortunately, there is no reliable way to swap out a different Guava version in Hadoop. 不幸的是,没有可靠的方法可以在Hadoop中换出另一个Guava版本。 Specifically, I recommend that you do not attempt to replace the Guava 11.0.2 jar that ships in the Hadoop distro. 具体来说,我建议您不要尝试替换Hadoop发行版中随附的Guava 11.0.2 jar。 Replacing this with a different Guava version is untested, and it would risk destabilizing the cluster. 未经测试的其他番石榴版本都将对其进行测试,这可能会破坏群集的稳定性。

The broader problem is that Hadoop's dependencies "leak" to its clients. 更广泛的问题是Hadoop的依赖关系“泄漏”给其客户端。 HADOOP-11656 is an unimplemented feature request that would isolate Hadoop's internal dependencies away from clients, so that you could more easily use common libraries like Guava at your desired version. HADOOP-11656是一个未实现的功能请求,它将使Hadoop的内部依赖项与客户端隔离开来,以便您可以更轻松地在所需版本中使用通用库(例如Guava)。 Meanwhile, until that feature is implemented, I think your only options are to stick to Guava 11.0.2 APIs, or possibly try inlining some of the Guava code that you really want into your own project directly. 同时,在实现该功能之前,我认为您唯一的选择就是坚持使用Guava 11.0.2 API,或者尝试将您真正想要的某些Guava代码直接内联到您自己的项目中。 The code for Queues#newArrayDeque is visible on GitHub . Queues#newArrayDeque的代码在GitHub上可见

public static <E> ArrayDeque<E> newArrayDeque() {
  return new ArrayDeque<E>();
}

In this particular case, it looks like it will be easy to replace your code with a direct call to the java.util.ArrayDeque constructor. 在这种特殊情况下,看起来很容易通过直接调用java.util.ArrayDeque构造函数来替换代码。 Thanks to the Java 7 diamond operator, it won't even be much more verbose. 感谢Java 7 Diamond运算符,它甚至不再冗长。

ArrayDeque<Entry<String, String>> a = new java.util.ArrayDeque<>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM