當前位置:首頁 » 編程軟體 » 編譯jar包指定jdk版本

編譯jar包指定jdk版本

發布時間: 2022-08-23 09:39:33

1. Intellij IDEA 怎麼向Eclipse一樣在編譯jar文件的時候修改jdk版本

可以試試
在jar包中,用winrar解壓一個類文件,然後在命令行下面輸入
javap -verbose classname
會輸出一些信息,大致如下:
Compiled from "HtmlCrawer.java"
public class org.eagleeye.html.HtmlCrawer extends java.lang.Object
SourceFile: "HtmlCrawer.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // org/eagleeye/html/HtmlCrawer
const #2 = Asciz org/eagleeye/html/HtmlCrawer;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz client;

2. 如何查看一個jar文件是用什麼版本jdk編譯的

有一種稍微麻煩的辦法,可以試試
在jar包中,用winrar解壓一個類文件,然後在命令行下面輸入
javap -verbose classname
會輸出一些信息,大致如下:

Compiled from "HtmlCrawer.java"
public class org.eagleeye.html.HtmlCrawer extends java.lang.Object
SourceFile: "HtmlCrawer.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // org/eagleeye/html/HtmlCrawer
const #2 = Asciz org/eagleeye/html/HtmlCrawer;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz client;
....

後面省略了,可以看到前面有兩行:
minor version: 0
major version: 50
表示了類文件的版本,具體內容可以參考:

http://hi..com/songdenggao/blog/item/3c354e4a877e0d2609f7ef93.html.
這裡面有一張表,可以很容易地查到版本

3. Linux上如何在運行JAR包的時候指定JDK

通常回答只有兩種,一種是製作一個可執行的 JAR 文件包,然後就可以像.chm 文檔一樣雙擊運行了;而另一種是使用 JET 來進行 編譯。但是
JET 是要用錢買的,而且據說 JET 也不是能把所有的 Java 程序都編譯成執行文件,性能也要打些折扣。所以,使用製作可執行 JAR
文件包的方法就是最佳選擇了,何況它還能保持 Java 的跨平台特性。

下面就來看看什麼是 JAR 文件包吧:

1. JAR 文件包

JAR
文件就是 Java Archive File,顧名思意,它的應用是與 Java 息息相關的,是 Java 的一種文檔格式。JAR 文件非常類似
ZIP 文件——准確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區別就是在 JAR 文件的內容中,包含了一個
META-INF/MANIFEST.MF 文件,這個文件是在生成 JAR 文件的時候自動創建的。舉個例子,如果我們具有如下目錄結構的一些文件:

==

`-- test

`-- Test.class

把它壓縮成 ZIP 文件 test.zip,則這個 ZIP 文件的內部目錄結構為:

test.zip

`-- test

`-- Test.class

如果我們使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,則這個 JAR 文件的內部目錄結構為:

test.jar

|-- META-INF

| `-- MANIFEST.MF

`-- test

`--Test.class

2. 創建可執行的 JAR 文件包

製作一個可執行的 JAR 文件包來發布你的程序是 JAR 文件包最典型的用法。

Java
程序是由若干個 .class 文件組成的。這些 .class
文件必須根據它們所屬的包不同而分級分目錄存放;運行前需要把所有用到的包的根目錄指定給 CLASSPATH 環境變數或者 java 命令的 -cp
參數;運行時還要到控制台下去使用 java 命令來運行,如果需要直接雙擊運行必須寫 Windows 的批處理文件 (.bat) 或者
Linux 的 Shell 程序。因此,許多人說,Java 是一種方便開發者苦了用戶的程序設計語言。

其實不然,如果開發者能
夠製作一個可執行的 JAR 文件包交給用戶,那麼用戶使用起來就方便了。在 Windows 下安裝 JRE (Java Runtime
Environment) 的時候,安裝文件會將 .jar 文件映射給 javaw.exe 打開。那麼,對於一個可執行的 JAR
文件包,用戶只需要雙擊它就可以運行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認是由 hh.exe
打開的)。那麼,現在的關鍵,就是如何來創建這個可執行的 JAR 文件包。

創建可執行的 JAR 文件包,需要使用帶 cvfm 參數的 jar 命令,同樣以上述 test 目錄為例,命令如下:

jar cvfm test.jar manifest.mf test


里 test.jar 和 manifest.mf 兩個文件,分別是對應的參數 f 和 m,其重頭戲在 manifest.mf。因為要創建可執行的
JAR 文件包,光靠指定一個 manifest.mf 文件是不夠的,因為 MANIFEST 是 JAR 文件包的特徵,可執行的 JAR
文件包和不可執行的 JAR 文件包都包含 MANIFEST。關鍵在於可執行 JAR 文件包的 MANIFEST,其內容包含了
Main-Class 一項。這在 MANIFEST 中書寫格式如下:

Main-Class: 可執行主類全名(包含包名)

例如,假設上例中的 Test.class 是屬於 test 包的,而且是可執行的類 (定義了 public static void main(String[]) 方法),那麼這個 manifest.mf 可以編輯如下:

Main-Class: test.Test <回車>;

這個 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個回車符結束即可。創建了 manifest.mf 文件之後,我們的目錄結構變為:

==

|-- test

| `-- Test.class

`-- manifest.mf

這時候,需要到 test 目錄的上級目錄中去使用 jar 命令來創建 JAR 文件包。也就是在目錄樹中使用「==」表示的那個目錄中,使用如下命令:

jar cvfm test.jar manifest.mf test

之後在「==」目錄中創建了 test.jar,這個 test.jar 就是執行的 JAR 文件包。運行時只需要使用 java -jar test.jar 命令即可。


要注意的是,創建的 JAR 文件包中需要包含完整的、與 Java 程序的包結構對應的目錄結構,就像上例一樣。而 Main-Class
指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包之前可以使用 java
<類名>; 來運行這個類,即在上例中 java test.Test 是可以正確運行的 (當然要在 CLASSPATH
正確的情況下)。

3. jar 命令詳解

jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin
目錄中,Windows 下文件名為 jar.exe,Linux 下文件名為 jar。它的運行需要用到 JDK 安裝目錄下 lib 目錄中的
tools.jar 文件。不過我們除了安裝 JDK 什麼也不需要做,因為 SUN 已經幫我們做好了。我們甚至不需要將 tools.jar 放到
CLASSPATH 中。

使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下:

jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ...

其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個,它們分別表示:

-c創建新的 JAR 文件包

-t列出 JAR 文件包的內容列表

-x展開 JAR 文件包的指定文件或者所有文件

-u更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)

[vfm0M] 中的選項可以任選,也可以不選,它們是 jar 命令的選項參數

-v生成詳細報告並列印到標准輸出

-f指定 JAR 文件名,通常這個參數是必須的

-m指定需要包含的 MANIFEST 清單文件

-0隻存儲,不壓縮,這樣產生的 JAR 文件包會比不用該參數產生的體積大,但速度更快

-M不產生所有項的清單(MANIFEST〕文件,此參數會忽略 -m 參數

[jar-文件] 即需要生成、查看、更新或者解開的 JAR 文件包,它是 -f 參數的附屬參數

[manifest-文件] 即 MANIFEST 清單文件,它是 -m 參數的附屬參數

[-C 目錄] 表示轉到指定目錄下去執行這個 jar 命令的操作。它相當於先使用 cd 命令轉該目錄下再執行不帶 -C 參數的 jar 命令,它只能在創建和更新 JAR 文件包的時候可用。

文件名 ... 指定一個文件/目錄列表,這些文件/目錄就是要添加到 JAR 文件包中的文件/目錄。如果指定了目錄,那麼 jar 命令打包的時候會自動把該目錄中的所有文件和子目錄打入包中。

下面舉一些例子來說明 jar 命令的用法:

1) jar cf test.jar test

該命令沒有執行過程的顯示,執行結果是在當前目錄生成了 test.jar 文件。如果當前目錄已經存在 test.jar,那麼該文件將被覆蓋。

2) jar cvf test.jar test

該命令與上例中的結果相同,但是由於 v 參數的作用,顯示出了打包過程,如下:

標明清單(manifest)

增加:test/(讀入= 0) (寫出= 0)(存儲了 0%)

增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

3) jar cvfM test.jar test

該命令與 2) 結果類似,但在生成的 test.jar 中沒有包含 META-INF/MANIFEST 文件,打包過程的信息也略有差別:

增加:test/(讀入= 0) (寫出= 0)(存儲了 0%)

增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

4) jar cvfm test.jar manifest.mf test

運行結果與 2) 相似,顯示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 內容不同,是包含了 manifest.mf 的內容

5) jar tf test.jar

在 test.jar 已經存在的情況下,可以查看 test.jar 中的內容,如對於 2) 和 3) 生成的 test.jar 分別應該此命令,結果如下;

對於 2)

META-INF/

META-INF/MANIFEST.MF

test/

test/Test.class

對於 3)

test/

test/Test.class

6) jar tvf test.jar

除顯示 5) 中顯示的內容外,還包括包內文件的詳細信息,如:

0 Wed Jun 19 15:39:06 GMT 2002 META-INF/

86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF

0 Wed Jun 19 15:33:04 GMT 2002 test/

7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class

7) jar xf test.jar

解開 test.jar 到當前目錄,不顯示任何信息,對於 2) 生成的 test.jar,解開後的目錄結構如下:

==

|-- META-INF

| `-- MANIFEST

`-- test

`--Test.class

8) jar xvf test.jar

運行結果與 7) 相同,對於解壓過程有詳細信息顯示,如:

創建:META-INF/

展開:META-INF/MANIFEST.MF

創建:test/

展開:test/Test.class

9) jar uf test.jar manifest.mf


test.jar 中添加了文件 manifest.mf,此使用 jar tf 來查看 test.jar 可以發現 test.jar
中比原來多了一個 manifest。這里順便提一下,如果使用 -m 參數並指定 manifest.mf 文件,那麼 manifest.mf
是作為清單文件 MANIFEST 來使用的,它的內容會被添加到 MANIFEST 中;但是,如果作為一般文件添加到 JAR
文件包中,它跟一般文件無異。

10) jar uvf test.jar manifest.mf

與 9) 結果相同,同時有詳細信息顯示,如:

增加:manifest.mf(讀入= 17) (寫出= 19)(壓縮了 -11%)

4. 關於 JAR 文件包的一些技巧

1) 使用 unzip 來解壓 JAR 文件


介紹 JAR 文件的時候就已經說過了,JAR 文件實際上就是 ZIP 文件,所以可以使用常見的一些解壓 ZIP 文件的工具來解壓 JAR
文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR
等來解壓是因為它們解壓比較直觀,方便。而使用 unzip,則是因為它解壓時可以使用 -d 參數指定目標目錄。

在解壓一個
JAR 文件的時候是不能使用 jar 的 -C 參數來指定解壓的目標的,因為 -C
參數只在創建或者更新包的時候可用。那麼需要將文件解壓到某個指定目錄下的時候就需要先將這具 JAR
文件拷貝到目標目錄下,再進行解壓,比較麻煩。如果使用 unzip,就不需要這么麻煩了,只需要指定一個 -d 參數即可。如:

unzip test.jar -d dest/

2) 使用 WinZip 或者 WinRAR 等工具創建 JAR 文件


面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR
等工具創建所需要 ZIP 壓縮包,再往這個 ZIP 壓縮包中添加一個包含 MANIFEST 文件的 META-INF 目錄即可。對於使用 jar
命令的 -m 參數指定清單文件的情況,只需要將這個 MANIFEST 按需要修改即可。

3) 使用 jar 命令創建 ZIP 文件


些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對 ZIP 文件進行解壓,即不能創建 ZIP 文件。如要創建一個
ZIP 文件,使用帶 -M 參數的 jar 命令即可,因為 -M 參數表示製作 JAR 包的時候不添加 MANIFEST
清單,那麼只需要在指定目標 JAR 文件的地方將 .jar 擴展名改為 .zip 擴展名,創建的就是一個不折不扣的 ZIP
文件了,如將上一節的第 3) 個例子略作改動:

jar cvfM test.zip test

4. 如何查看一個jar文件是用什麼版本jdk編譯的

有一種稍微麻煩的辦法,可以試試
在jar包中,用winrar解壓一個類文件,然後在命令行下面輸入
javap -verbose classname
會輸出一些信息,大致如下:

Compiled from "HtmlCrawer.java"
public class org.eagleeye.html.HtmlCrawer extends java.lang.Object
SourceFile: "HtmlCrawer.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // org/eagleeye/html/HtmlCrawer
const #2 = Asciz org/eagleeye/html/HtmlCrawer;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz client;
....

後面省略了,可以看到前面有兩行:
minor version: 0
major version: 50
表示了類文件的版本,具體內容可以參考:

2008-05-08 17:27 class version一:要解決的問題

我們在嘗鮮 JDK1.5 的時候,相信不少人遇到過 Unsupported major.minor version 49.0 錯誤,當時定會茫然不知所措。因為剛開始那會兒,網上與此相關的中文資料還不多,現在好了,網上一找就知道是如何解決,大多會告訴你要使用 JDK 1.4 重新編譯。那麼至於為什麼,那個 major.minor 究竟為何物呢?這就是本篇來講的內容,以使未錯而先知。

我覺得我是比較幸運的,因為在遇到那個錯誤之前已研讀過《深入 Java 虛擬機》第二版,英文原書名為《Inside the Java Virtual Machine》( Second Edition),看時已知曉 major.minor 藏匿於何處,但沒有切身體會,待到與 Unsupported major.minor version 49.0 真正會面試,正好是給我驗證了一個事實。

首先我們要對 Unsupported major.minor version 49.0 建立的直接感覺是:JDK1.5 編譯出來的類不能在 JVM 1.4 下運行,必須編譯成 JVM 1.4 下能運行的類。(當然,也許你用的還是 JVM 1.3 或 JVM 1.2,那麼就要編譯成目標 JVM 能認可的類)。這也解決問題的方向。

二:major.minor 棲身於何處

何謂 major.minor,且又居身於何處呢?先感性認識並找到 major.minor 來。

寫一個 Java Hello World! 代碼,然後用 JDK 1.5 的編譯器編譯成,HelloWorld.java

public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }

用 JDK 1.5 的 javac HelloWorld.java 編譯出來的位元組碼 HelloWorld.class 用 UltraEdit 打開來的內容如圖所示:

從上圖中我們看出來了什麼是 major.minor version 了,它相當於一個軟體的主次版本號,只是在這里是標識的一個 Java Class 的主版本號和次版本號,同時我們看到 minor_version 為 0x0000,major_version 為 0x0031,轉換為十制數分別為0 和 49,即 major.minor 就是 49.0 了。

三:何謂 major.minor 以及何用

Class 文件的第 5-8 位元組為 minor_version 和 major_version。Java class 文件格式可能會加入新特性。class 文件格式一旦發生變化,版本號也會隨之變化。對於 JVM 來說,版本號確定了特定的 class 文件格式,通常只有給定主版本號和一系列次版本號後,JVM 才能夠讀取 class 文件。如果 class 文件的版本號超出了 JVM 所能處理的有效范圍,JVM 將不會處理該 class 文件。

在 Sun 的 JDK 1.0.2 發布版中,JVM 實現支持從 45.0 到 45.3 的 class 文件格式。在所有 JDK 1.1 發布版中的 JVM 都能夠支持版本從 45.0 到 45.65535 的 class 文件格式。在 Sun 的 1.2 版本的 SDK 中,JVM 能夠支持從版本 45.0 到46.0 的 class 文件格式。

1.0 或 1.2 版本的編譯器能夠產生版本號為 45.3 的 class 文件。在 Sun 的 1.2 版本 SDK 中,Javac 編譯器默認產生版本號為 45.3 的 class 文件。但如果在 javac 命令行中指定了 -target 1.2 標志,1.2 版本的編譯器將產生版本號為 46.0 的 class 文件。1.0 或 1.1 版本的 JVM 上不能運行使用-target 1.2 標志所產生的 class 文件。

JVM 實現的 第二版中修改了對 class 文件主版本號和次版本號的解釋。對於第二版而言,class 文件的主版本號與 Java 平台主發布版的版本號保持一致(例如:在 Java 2 平台發布版上,主版本號從 45 升至 46),次版本號與特定主平台發布版的各個發布版相關。因此,盡管不同的 class 文件格式可以由不同的版本號表示,但版本號不一樣並不代表 class 文件格式不同。版本號不同的原因可能只是因為 class 文件由不同發布版本的 java 平台產生,可能 class 文件的格式並沒有改變。

上面三段節選自《深入 Java 虛擬機》,啰嗦一堆,JDK 1.2 開啟了 Java 2 的時代,但那個年代仍然離我們很遠,我們當中很多少直接跳在 JDK 1.4 上的,我也差不多,只是項目要求不得不在一段時間里委屈在 JDK 1.3 上。不過大致我們可以得到的信息就是每個版本的 JDK 編譯器編譯出的 class 文件中都帶有一個版本號,不同的 JVM 能接受一個范圍 class 版本號,超出范圍則要出錯。不過一般都是能向後兼容的,知道 Sun 在做 Solaris 的一句口號嗎?保持對先前版本的 100% 二進制兼容性,這也是對客戶的投資保護。

四:編譯器比較及症節之所在

現在不妨從 JDK 1.1 到 JDK 1.7 編譯器編譯出的 class 的默認 minor.major version 吧。(又走到 Sun 的網站上翻騰出我從來都沒用過的古董來)

JDK 編譯器版本 target 參數 十六進制 minor.major 十進制 minor.major jdk1.1.8 不能帶 target 參數 00 03 00 2D 45.3 jdk1.2.2 不帶(默認為 -target 1.1) 00 03 00 2D 45.3 jdk1.2.2 -target 1.2 00 00 00 2E 46.0 jdk1.3.1_19 不帶(默認為 -target 1.1) 00 03 00 2D 45.3 jdk1.3.1_19 -target 1.3 00 00 00 2F 47.0 j2sdk1.4.2_10 不帶(默認為 -target 1.2) 00 00 00 2E 46.0 j2sdk1.4.2_10 -target 1.4 00 00 00 30 48.0 jdk1.5.0_11 不帶(默認為 -target 1.5) 00 00 00 31 49.0 jdk1.5.0_11 -target 1.4 -source 1.4 00 00 00 30 48.0 jdk1.6.0_01 不帶(默認為 -target 1.6) 00 00 00 32 50.0 jdk1.6.0_01 -target 1.5 00 00 00 31 49.0 jdk1.6.0_01 -target 1.4 -source 1.4 00 00 00 30 48.0 jdk1.7.0 不帶(默認為 -target 1.6) 00 00 00 32 50.0 jdk1.7.0 -target 1.7 00 00 00 33 51.0 jdk1.7.0 -target 1.4 -source 1.4 00 00 00 30 48.0 Apache Harmony 5.0M3 不帶(默認為 -target 1.2) 00 00 00 2E 46.0 Apache Harmony 5.0M3 -target 1.4 00 00 00 30 48.0
上面比較是 Windows 平台下的 JDK 編譯器的情況,我們可以此作些總結:

1) -target 1.1 時 有次版本號,target 為 1.2 及以後都只用主版本號了,次版本號為 0
2) 從 1.1 到 1.4 語言差異比較小,所以 1.2 到 1.4 默認的 target 都不是自身相對應版本
3) 1.5 語法變動很大,所以直接默認 target 就是 1.5。也因為如此用 1.5 的 JDK 要生成目標為 1.4 的代碼,光有 -target 1.4 不夠,必須同時帶上 -source 1.4,指定源碼的兼容性,1.6/1.7 JDk 生成目標為 1.4 的代碼也如此。
4) 1.6 編譯器顯得較為激進,默認參數就為 -target 1.6。因為 1.6 和 1.5 的語法無差異,所以用 -target 1.5 時無需跟著 -source 1.5。
5) 注意 1.7 編譯的默認 target 為 1.6
6) 其他第三方的 JDK 生成的 Class 文件格式版本號同對應 Sun 版本 JDK
7) 最後一點最重要的,某個版本的 JVM 能接受 class 文件的最大主版本號不能超過對應 JDK 帶相應 target 參數編譯出來的 class 文件的版本號。

上面那句話有點長,一口氣讀過去不是很好理解,舉個例子:1.4 的 JVM 能接受最大的 class 文件的主版本號不能超過用 1.4 JDK 帶參數 -target 1.4 時編譯出的 class 文件的主版本號,也就是 48。

因為 1.5 JDK 編譯時默認 target 為 1.5,出來的位元組碼 major.minor version 是 49.0,所以 1.4 的 JVM 是無法接受的,只有拋出錯誤。

那麼又為什麼從 1.1 到 1.2、從 1.2 到 1.3 或者從 1.3 到 1.4 的 JDK 升級不會發生 Unsupported major.minor version 的錯誤呢,那是因為 1.2/1.3/1.4 都保持了很好的二進制兼容性,看看 1.2/1.3/1.4 的默認 target 分別為 1.1/1.1/1.2 就知道了,也就是默認情況下1.4 JDK 編譯出的 class 文件在 JVM 1.2 下都能載入執行,何況於 JVM 1.3 呢?(當然要去除使用了新版本擴充的 API 的因素)

五:找到問題解決的方法

那麼現在如果碰到這種問題該知道如何解決了吧,還會像我所見到有些兄弟那樣,去找個 1.4 的 JDK 下載安裝,然後用其重新編譯所有的代碼嗎?其實大可不必如此費神,我們一定還記得 javac 還有個 -target 參數,對啦,可以繼續使用 1.5 JDK,編譯時帶上參數 -target 1.4 -source 1.4 就 OK 啦,不過你一定要對哪些 API 是 1.5 JDK 加入進來的了如指掌,不能你的 class 文件拿到 JVM 1.4 下就會 method not found。目標 JVM 是 1.3 的話,編譯選項就用 -target 1.3 -source 1.3 了。

相應的如果使用 ant ,它的 javac 任務也可對應的選擇 target 和 source

<javac target="1.4" source="1.4" ............................/>

如果是在開發中,可以肯定的是現在真正算得上是 JAVA IDE 對於工程也都有編譯選項設置目標代碼的。例如 Eclipse 的項目屬性中的 Java Compiler 設置,如圖

自已設定編譯選項,你會看到選擇不同的 compiler compliance level 是,Generated class files compatibility 和 Source compatibility 也在變,你也可以手動調整那兩項,手動設置後你就不用很在乎用的什麼版本的編譯器了,只要求他生成我們希望的位元組碼就行了,再引申一下就是即使源代碼是用 VB 寫的,只要能編譯成 JVM 能執行的位元組碼都不打緊。在其他的 IDE 也能找到相應的設置對話框的。

其他時候,你一定要知道當前的 JVM 是什麼版本,能接受的位元組碼主版本號是多少(可對照前面那個表)。獲息當前 JVM 版本有兩種途徑:

第一:如果你是直接用 java 命令在控制台執行程序,可以用 java -version 查看當前的 JVM 版本,然後確定能接受的 class 文件版本

第二:如果是在容器中執行,而不能明確知道會使用哪個 JVM,那麼可以在容器中執行的程序中加入代碼System.getProperty("java.runtime.version"); 或 System.getProperty("java.class.version"),獲得 JVM 版本和能接受的 class 的版本號。

最後一絕招,如果你不想針對低版本的 JVM 用 target 參數重新編譯所有代碼;如果你仍然想繼續在代碼中用新的 API 的話;更有甚者,你還用了 JDK 1.5 的新特性,譬如泛型、自動拆裝箱、枚舉等的話,那你用 -target 1.4 -source 1.4 就沒法編譯通過,不得不重新整理代碼。那麼告訴你最後一招,不需要再從源代碼著手,直接轉換你所正常編譯出的位元組碼,繼續享用那些新的特性,新的 API,那就是:請參考之前的一篇日誌:Retrotranslator讓你用JDK1.5的特性寫出的代碼能在JVM1.4中運行,我就是這么用的,做好測試就不會有問題的。

六:再議一個實際發生的相關問題

這是一個因為拷貝 Tomcat 而產生的 Unsupported major.minor version 49.0 錯誤。情景是:我本地安裝的是 JDK 1.5,然後在網上找了一個 EXE 的 Tomcat 安裝文件安裝了並且可用。後來同事要一個 Tomcat,不想下載或安裝,於是根據我以往的經驗是把我的 Tomcat 整個目錄拷給他應該就行了,結果是拿到他那裡瀏覽 jsp 文件都出現 Unsupported major.minor version 49.0 錯誤,可以確定的是他安裝的是 1.4 的 JDK,但我還是有些納悶,先前對這個問題還頗有信心的我傻眼了。慣性思維是編譯好的 class 文件拿到低版本的 JVM 會出現如是異常,可現並沒有用已 JDK 1.5 編譯好的類要執行啊。

後來仔細看異常信息,終於發現了 %TOMCAT_HOME%\common\lib\tools.jar 這一眉目,因為 jsp 文件需要依賴它來編譯,打來這個 tools.jar 中的一個 class 文件來看看,49.0,很快我就明白原來這個文件是在我的機器上安裝 Tomcat 時由 Tomcat 安裝程序從 %JDK1.5%\lib 目錄拷到 Tomcat 的 lib 目錄去的,造成在同事機器上編譯 JSP 時是 1.4 的 JVM 配搭著 49.0 的 tools.jar,那能不出錯,於是找來 1.4 JDK 的 tools.jar 替換了 Tomcat 的就 OK 啦。

5. java 如何改變編譯文件的jdk版本

如果你用的是MyEclipse的話 這樣試試 window---preferences---java---installed JRES 添加一個1.5的

6. 如何將源代碼編譯成jar包

先打開命令提示符(win2000或在運行框里執行cmd命令,win98為DOS提示符),輸入jar Chelp,然後回車(如果你盤上已經有了jdk1.1或以上版本),看到什麼:

用法:jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ...

選項:

-c 創建新的存檔

-t 列出存檔內容的列表

-x 展開存檔中的命名的(或所有的〕文件

-u 更新已存在的存檔

-v 生成詳細輸出到標准輸出上

-f 指定存檔文件名

-m 包含來自標明文件的標明信息

-0 只存儲方式;未用zip壓縮格式

-M 不產生所有項的清單(manifest〕文件

-i 為指定的jar文件產生索引信息

-C 改變到指定的目錄,並且包含下列文件:

如果一個文件名是一個目錄,它將被遞歸處理。

清單(manifest〕文件名和存檔文件名都需要被指定,按'm' 和 'f'標志指定的相同順序。

首先在資源文件當前目錄寫一個清單文件example.mf

mf文件應是以下格式:
第一行為:
Main-Class: Hello
然後最少兩個空行。
其中的Hello.class是你寫的程序中main函數所在的那個類名。
有兩點必須記得:
1,在第一行中"Main-class:"之後一定要有一個空格。後有最少兩個空行
2,類名不能寫成Hello.class的格式,要省了後輟。
我試過了,你錯的原因是"Main-class:"之後沒有一個空格。
在CLASS目錄下運行:jar cfm example.jar example.mf A.class B.class

示例1:將兩個class文件存檔到一個名為 'classes.jar' 的存檔文件中:


jar cvf classes.jar Foo.class Bar.class

示例2:用一個存在的清單(manifest)文件 'mymanifest' 將 foo/ 目錄下的所有文件存檔到一個名為 'classes.jar' 的存檔文件中:

jar cvfm classes.jar mymanifest -C foo/ .

來個小例子試試看:

我們只有一個HelloWorld,如下:

public class HelloWorld{
public static void main(String[ ] args){
System.out.println("Hi, Hello World!");
}
}
將這個java文件存到C盤跟目錄下,ok,接下來,

在先前打開的命令提示符下(跳轉到C盤提示符下),我們輸入javac HelloWorld.java,然後繼續輸入:jar cvf hello.jar HelloWorld.class,回車後去你的C盤看看,多了什麼,沒錯 hello.jar 。

基本的步驟我們現在都知道了,你可以自己去嘗試一下隨著jar後面的參數的不同,結果有什麼變化。
緊接著我們看看如何運行我們的jar包。

在進入正題之前,你要先打開我們剛剛做好的jar包看看,多了什麼呢,META-INF目錄?再看看裡面是什麼,還有一個MANIFEST.MF文件是不是?用文本編輯器(我這里是UltraEdit)打開它看看:

Manifest-Version: 1.0
Created-By: 1.4.2 (Sun Microsystems Inc.)

就是這樣。這里我們對它進行修改,加一句:Main-Class: HelloWorld (在第三行)。這個就是我們之前寫的那個類,也就是我們的入口類。也即,

Manifest-Version: 1.0
Created-By: 1.4.2 (Sun Microsystems Inc.)
Main-Class: HelloWorld

接下來,我們在命令提示符里執行:

jar umf MANIFEST.MF app.jar (應該是hello.jar吧)

這樣我們使用了我們自己的MANIFEST.MF文件對原來默認的進行了更新。你不妨可以再進去看看是不是添上了Main-
Class: HelloWorld這一句。 (是嗎,我怎麼沒試出來,提示
java.io.FileNotFoundException:MANIFEST.MF(系統找不到指定的文件)怎麼回事?
)

Ok,這個最後的一步了,來驗證我們做的一切,在命令提示符中輸入:

java -jar hello.jar(執行)

出現了什麼, Hi, Hello World!

我們再來看看jar文件在tomcat中發布,注意:在tomcat中我們就不能再用jar這種格式,而改war格式,它是專門用於web應用的,其實整個過程下來基本上和jar是類似的:

先准備我們要打包的資源。

找到存放tomcat的webapps目錄,進到其中,新建一個文件夾,這里命名為hello,再進去新建WEB-INF文件夾,再進去新
建 classes文件夾,此時我們也將我們唯一的servlet,HelloWorld.java放到這里,在與classes目錄同級下建立一文
件 web.xml。Ok,目前我們初步建立了一個簡單的web應用。

這是HelloWorld.java:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("");
out.println("");
out.println("");
out.println("Hello, World!");
out.println("");
}
}//end here!

對它編譯。下面是web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.
//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
</web-app>

在命令提示符下進到先前創制的hello目錄下,執行 jar cvf hello.war * ,我們便得到hello.war。將它拷貝至webapps目錄下,ok,來看最後一步,打開tomcat的目錄conf中的server.xml,加入:

<Context path="/hello" docBase="hello.war" debug="0" reloadable="true"/>
大功告成!運行它,啟動tomcat,後在瀏覽器中輸入http://localhost:8080/hello/HelloWorld,有了嗎?

最後,如果你想用ant來完成以上的打包活動,下面就告訴你:
對於jar來說。在build.xml中,

<target name="jar">
<jar destfile="${app_home}/hello.jar">
<fileset dir="${dest}" includes="**"/>
<!--fileset dir="${dest}" includes="**/action.properties"/-->
</jar>
</target>
對於war,

<war warfile="hello.war" webxml="./WEB-INF/web.xml">
<fileset dir="html"/>
<lib dir="lib/">
<exclude name="oracle*.jar"/>
</lib>
<classes dir="build/servlets">
<include name="**/*.class"/>
</classes>
</war>
好了,就這么多,希望對你有點幫助。:)

補充:

jar基本操作:

1. 創建jar文件
jar cf jar-file input-file(s)
c---want to Create a JAR file.
f---want the output to go to a file rather than to stdout.
eg: 1)jar cf myjar.jar query_maintain_insert.htm
2)jar cvf myjar.jar query_maintain_insert.htm
v---Proces verbose(詳細的) output.

3)jar cvf myjar.jar query_maintain_insert.htm mydirectory
4)jar cv0f myjar.jar query_maintain_insert.htm mydirectory
0---don't want the JAR file to be compressed.
5)jar cmf MANIFEST.MF myjar.jar yahh.txt
m---Used to include manifest information from an existing manifest file.
6)jar cMf MANIFEST.MF myjar.jar yahh.txt
M---the default manifest file should not be proced.
7)jar cvf myjar.jar *
*---create all contents in current directory.

2. 察看jar文件
jar tf jar-file
t---want to view the Table of contents of the JAR file.
eg: 1)jar vft yahh.jar
v---Proces verbose(詳細的) output.

3. 提取jar文件
jar xf jar-file [archived-file(s)]
x---want to extract files from the JAR archive.
eg: 1)jar xf yahh.jar yahh.txt(僅提取文件yahh.txt)

2)jar xf yahh.jar alex/yahhalex.txt(僅提取目錄alex下的文件yahhalex.txt)

3)jar xf yahh.jar(提取該jar包中的所有文件或目錄)

4. 修改Manifest文件
jar cmf manifest-addition jar-file input-file(s)
m---Used to include manifest information from an existing manifest file.

5. 更新jar文件
jar uf jar-file input-file(s)
u---want to update an existing JAR file

7. java編譯,提示JDK版本錯誤!

步驟一:

修改Eclipse/Myeclipse JDK版本:

WindowàPreferenceàJavaàInstalled JREs

在相應的JDK版本前面打鉤

8. 如何看一個jar 包的jdk版本號

用7-zip打開.jar包,查看META-INFMANIFEST.MF中的內容,Build-Jdk屬性就是JDK的版本,比如:

Build-Jdk: 1.5.0_221

說明其JDK版本為1.5.0.22。
注意:一個.jar文件中,如果沒有這個欄位,就必須通過下面一種方法來查看

通過反編譯.class文件來查看

解壓.jar包,能得到.class文件。用JDK自帶的javap反編譯.class文件,用如下命令:

javap -verbose Configuration.class1

查看得到的信息中,major version屬性的內容,如下

major version: 521

說明這個.class文件是由JDK1.8編譯得到的。

  • J2SE 6.0 = 50 (0x32 hex)

  • J2SE 5.0 = 49 (0x31 hex)

  • JDK 1.4 = 48 (0x30 hex)

  • JDK 1.3 = 47 (0x2F hex)

  • JDK 1.2 = 46 (0x2E hex)

  • JDK 1.1 = 45 (0x2D hex)

注意:一個.jar包中可能有多個.class文件,每個.class的JDK版本可能會不一樣(編譯器多個項目設置不同)

9. 如何獲取jar包的jdk版本號

1,通過class文件

將編譯出來的class文件拖入到eclipse下,如:

可以看到,版本號為1.5

2,javap命令查看

javap MediaManager -verbose > majorver.txt

其中MediaManager為類名,將版本信息輸出到majorver.txt,版本信息如下:

可以看到jdk版本為47。major version和jdk版本對應關系如下:

Major version Java

46 Java 1.2

47 Java 1.3

48 Java 1.4

49 Java 5

50 Java 6

51 Java 7

jar的版本號必須和虛擬機相對應,否則會出現版本不支持的錯誤。

熱點內容
matlab稀疏矩陣存儲 發布:2025-02-06 03:07:54 瀏覽:838
國際服2b2t伺服器地址 發布:2025-02-06 03:06:28 瀏覽:390
c語言輸出b 發布:2025-02-06 03:06:27 瀏覽:31
普通火車wifi密碼多少 發布:2025-02-06 03:04:20 瀏覽:436
可編程監控 發布:2025-02-06 03:03:33 瀏覽:645
c語言取隨機數 發布:2025-02-06 02:46:57 瀏覽:863
uc緩存的視頻卡住 發布:2025-02-06 02:17:05 瀏覽:144
解壓同學介紹 發布:2025-02-06 02:13:10 瀏覽:776
icsftp 發布:2025-02-06 02:12:59 瀏覽:325
ftp跨域上傳文件 發布:2025-02-06 02:09:22 瀏覽:822