类路径问题

问题描述:

我想运行一个map/reduce作业,我得到一个java.lang.NoSuchMethodError。我在这方面做了一些研究,当我的代码执行(未编译)时出现这种情况。在编译过程中,类和方法的正确版本存在,但在尝试运行时,正确的方法不可用。导致此问题的jar文件是番石榴。我从印刷的堆栈知道这一点。类路径问题

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

这罐子是Hadoop的类路径的一部分,因为它配备了CDH VERSON 5.3.0,我使用:尝试执行下面的代码行,当我抛出一个错误。我曾尝试将类番石榴的正确版本添加到类路径中,但错误不会更改。我的问题如下:

  1. 我相信我已经正确地确定了这个问题。这对你来说似乎合理吗?我从来没有遇到过这个错误。

  2. 我相信我需要从类路径中删除旧版本的番石榴并添加新的。但是,我真的不知道从哪里开始纠正这个问题。发给hadoop jar的命令不包含旧版本的guava(在-libjar parm中)。当我发出命令“hadoop classpath”时,jar是hadoop classpath的一部分。所以我假设有一些我可以编辑的hadoop配置文件让它消失。这是正确的路要走,还是有其他我需要做的事情?

我使用的Java 7,CDH 5.3.0,NetBeans的8

TIA

+0

我的头顶 - 你可以把新的jar放在classpath的开头吗? –

+0

据我所知,我可以通过在调用Hadoop时使用-libjar parm添加jar来将jar添加到classpath中。我使用它添加了jar,并在最后添加了它。 – Crackerman

+0

在这种情况下,你可以尝试这样的:'export HADOOP_CLASSPATH =/path/to/newjar.jar:$ HADOOP_CLASSPATH;' –

当时我写这篇文章的时候,Hadoop的对番石榴11.0.2版的依赖。它在内部实现中使用了相当多的库。

根据Guava JavaDocs,在版本12.0中添加了Queues#newArrayDeque方法。如果您的代码编译成功,那么这意味着在构建时您的编译类路径上可以使用Guava版本12.0或更高版本,但由于版本11.0.2是由Hadoop在运行时提供的,因此该方法不存在,导致NoSuchMethodError

不幸的是,没有可靠的方法在Hadoop中换出不同的Guava版本。具体而言,我建议您不要试图替换Hadoop发行版中发布的Guava 11.0.2 jar。用不同的Guava版本替换这个版本是未经测试的,它可能会破坏集群的稳定性。

更广泛的问题是Hadoop的依赖性“泄露”给客户端。 HADOOP-11656是一个未实现的功能请求,它可以将Hadoop的内部依赖关系从客户端中分离出来,以便您可以更方便地在所需版本中使用常见的库,如Guava。同时,在实现该功能之前,我认为您唯一的选择是坚持使用Guava 11.0.2 API,或者尝试直接将您真正想要的一些Guava代码嵌入到自己的项目中。代码为Queues#newArrayDeque is visible on GitHub

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

在这种特殊情况下,它看起来会很容易通过直接调用java.util.ArrayDeque构造来代替你的代码。感谢Java 7钻石操作员,它甚至不会更冗长。

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