2012-03-18 18 views
13

這是我的同事的一個錯誤:有一個名爲test.jar的jar,他修復了一個bug。然後他重新編譯代碼,並建立了一個名爲testnew.jar的新jar。問題是他把這兩個jar放到classpath中的一個文件夾中。 所以當程序運行時,行爲是一種混亂。我不知道發生了什麼,但刪除test.jar後,再次罰款。當類路徑中包含兩個相同的jar時,JVM如何工作

所以我想知道什麼是JVM的行爲。它在第一個jar中使用類文件嗎?或者是其他東西?

謝謝。

回答

4

是的,默認情況下它使用第一個jar中的類。這就是爲什麼你必須檢查庫目錄重複。爲我和我的同事做了很多次。

+0

所以似乎沒有機制來避免這種情況。 – XiaoYao 2012-03-18 09:54:54

+1

這是一個有趣的*假設*,但你有任何參考支持? – 2012-03-18 10:50:50

+0

@曉堯避免這種情況的方法是不要兩次添加相同的東西。如果你複製同樣的東西,它有一個定義的行爲,所以它不必成爲一個問題。 – 2012-03-18 10:54:32

2

如果有重複項,它會讀取類路徑中第一個出現的重複項。

編輯 一般類路徑文件看起來是這樣的..

<classpath> 
     <classpathentry kind="lib" path="C:/Temp/test.jar"/> 
     <classpathentry kind="lib" path="C:/Temp/testnew.jar"/> 
    <classpathentry kind="output" path="build/classes"/> 
</classpath> 

如果你的類路徑看起來像上面,那麼你的JVM會考慮Test.jar的第一,因爲它第一次出現在類路徑。如果您想自己測試它,請嘗試移動test.jar條目上方的testnew.jar的classpatterntry。你會看到它現在引用了testnew.jar而不是test.jar。

參考:FindingClasses

+0

你有參考嗎? – 2012-03-18 10:51:00

+0

@ T.J.Crowder:好吧,我沒有書面證據說明這一點,但我已經自行測試了。這是我觀察到的默認行爲。看到我上面的編輯,我做了類似的事情來證明它。 – 2012-03-18 11:07:51

+0

'@ Shashank':那麼你*不能*信任這個行爲,它可以根據類加載器或者在使用相同類加載器的情況下使用,如果它使用了一些奇怪的查找方法。詳情請參閱我的回答。 – 2012-03-18 11:09:27

6

據我所知,它是沒有定義。

Java有一個可插拔的類加載器系統,並由此知道會發生什麼的唯一方式是看ClassLoader class的文件,可能是在特定的ClassLoader#findClass method,不定義此行爲,並尋求在JLSJVM specs的相關部分中,這兩者在這方面似乎都沒有對類加載器指定約束。因此,除非Web容器使用的類加載器記錄了行爲,否則無法確定哪個類將被加載。

賠率是是第一個發現匹配類的二進制名稱將在一個加載,但有行爲之間的差異,我們假設是這種情況,並指定該行爲, /或記錄。

+0

我在java文檔中找到[this](http://docs.oracle.com/javase/1.4.2/docs/tooldocs/findingclasses.html)。請參閱「Java啓動程序如何查找JAR類路徑類」一節....我認爲它表明JAR文件出現在JAR-class-path中的任何較早的類路徑條目之後,並且在任何條目之前在類路徑後面出現._......所以你不認爲這將是默認的行爲,以查看類路徑??? – 2012-03-18 11:21:48

+0

@ ShashankKadne:好交易,以便告訴你什麼'Java'工具(Java啓動器)確實(至少,它在大約10年前v1.4.2中做了什麼,但我懷疑它已經改變了)。這對於使用'java'工具時非常有用。它通常不會告訴你什麼類加載器會做什麼。 OP沒有說它是什麼樣的應用程序(桌面應用程序通過'java'啓動,Web應用程序由容器定義類加載器等)。 – 2012-03-18 11:32:07

1

JVM加載類路徑上的任何特定JAR。由於Java 6也有一個通配符。以下是幾個例子。

java -cp ".:lib/example.jar" Main 

以上只會載入在當前目錄和example.jar中找到的類。而下一個示例將使用任何jar從中加載類。

java -cp ".:lib/*" Main 

我不認爲針對JAR目錄中首先找到一個類被檢查的順序定義,只是它曾經下令OS上市文件時給了。

很可能你的IDE(或者你用來運行你的程序的任何東西)正在使用後一種符號來運行你的程序。你可以改變它,以便使用前者,但是如果你改變了jar的名字或者添加了新的名字,它會中斷。

相關問題