2010-03-15 189 views
8

我想打包一段代碼,絕對必須在Java 1.5上運行。如果虛擬機爲1.6 VM,則代碼的一部分可以「增強」程序。Java:最簡單的方法來打包Java 1.5和1.6代碼

基本上它的這種方法:

private long[] findDeadlockedThreads() { 
    // JDK 1.5 only supports the findMonitorDeadlockedThreads() 
    // method, so you need to comment out the following three lines 
    if (mbean.isSynchronizerUsageSupported()) 
     return mbean.findDeadlockedThreads(); 
    else 
     return mbean.findMonitorDeadlockedThreads(); 
    } 

什麼是有這個編譯 1.5,但做1.6方法調用1.6時,最簡單的方法?

在過去,我通過編譯一個獨特的1.6類來完成類似的工作,我將其打包到應用程序中,並在1.6上使用ClassLoader進行實例化(因爲1.6 JVM完美地混合了0x32和0x31類),但我認爲這有點矯枉過正(並且有點痛苦,因爲在構建過程中你必須建立0x31和0x32 .class文件)。

如果我想在1.5上編譯上述方法,該怎麼辦?也許使用反射,但再怎麼(我不熟悉,在所有反射)

注意:如果你好奇,上述方法來自這篇文章:http://www.javaspecialists.eu/archive/Issue130.html

(但我不想「評論三條線」就像文章中的一樣,我希望它能夠在1.5和1.6上編譯和運行)

回答

3

你不能在1.5上編譯它,但是你可以在1.6上編譯目標選項設置爲1.5這將產生1.5的字節碼),並在代碼中使用反射來確定該方法是否可用。

此代碼將查找方法: mbean.getClass()。getMethod(「findDeadlockedThreads」,new Class [0]); 問題是,如果該方法不存在而不是簡單地返回null或類似的東西,則會引發NoSuchMethodException。這意味着,您需要這樣的代碼:

try 
{ 
    mbean.getClass().getMethod("findDeadlockedThreads", new Class<?>[0]); 
    return mbean.findDeadlockedThreads(); 
} 
catch(NoSuchMethodException ex) 
{ 
    return mbean.findMonitorDeadlockedThreads(); 
} 

這不是很好,因爲它使用Exception來做出決定。這可能不是很快。另一種方法是使用getMethods,如果方法可用,則遍歷返回的列表。這也不是很快。

編輯:克里斯托弗Oezbek在評論中建議只檢查一次存在的方法,並保存結果,以避免Try-catch-block的開銷。這是正確的,一個很好的解決方案。 matt b警告說,Java-Compiler的目標選項沒有檢查,如果所使用的類和方法在Java 1.5下可用。這是正確的(否則它將無法工作,因爲你想用1.6方法編譯),這意味着程序應該在1.5-VM下仔細測試,以避免這個問題。感謝您的評論。

+0

@Mnementh:OK,但隨後會是什麼反映代碼的樣子? – SyntaxT3rr0r 2010-03-15 16:17:23

+0

我編輯了我的答案以包含反射代碼。 – Mnementh 2010-03-15 16:23:52

+0

@Menmenth:+1好極了......我會盡力在今天下午設置它:) – SyntaxT3rr0r 2010-03-15 16:26:47

2

編譯爲1.5。

在你的代碼中使用反射。您可以從Class接口獲取Method對象;它有一個invoke方法,它將mbean實例作爲參數。像這樣:

Class c = mbean.getClass(); //也可以做YourClass.class來獲得這個

方法m = c。getMethod( 「findMonitorDeadLockedThreads」); //或任何其他方法(參數 方法與類指定...第二個參數getMethod)

m.invoke(的MBean)//調用方法與實例

當然你不每次都不必這樣做;在構造函數中設置Method引用,然後根據需要調用正確的引用。

+0

@danpaq:這是一個簡單的情況,因爲沒有參數傳遞給方法。所以從Mnementh和你的回答中我可以看出,思考是要走的路......所以我會嘗試你在這裏提出的建議。 – SyntaxT3rr0r 2010-03-15 16:22:06

+0

@WizardOfOdds:如果你認爲這個建議有價值,請注意。 – 2010-03-15 16:25:23

1

Maven讓你可以很容易地使用配置文件來做到這一點。配置文件背後的想法是,您希望基於某些標準構建兩種不同版本的東西。在此特定示例中,您可以定義jdk15jdk16配置文件,指定要編譯哪個JDK版本,並指示它在jdk15配置文件中包含該類的一個副本,而另一個包含在jdk16中。

要開始,請參閱:

http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html

介紹如何做的問題的不同的JDK版本的一部分。

來處理這個問題的第二部分,使用取決於JDK版本類的不同的定義,請參閱本:

Maven - Include Different Files at Build Time

+0

對不起,希望有所幫助...我現在沒有空閒時間向您展示完整的Maven構建腳本。 – 2010-03-15 16:18:50

+0

爲了確保我能理解你說的是正確的:我需要打包併發佈一個獨特的* .jar *,在1.5和1.6上使用1.6功能時,我可以使用Mave配置文件進行操作嗎? – SyntaxT3rr0r 2010-03-15 16:20:54

+0

@WizardOfOdds:是的,這正是我之前試圖描述的。我修改了我的回覆,以獲得比我在這裏描述的更好的鏈接。 – 2010-03-15 18:56:41