2015-12-21 232 views
2

我想運行一個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;' –

回答

0

當時我寫這篇文章的時候,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<>();