JAVA jar命令(一)-jar打包class文件

jar包本質上是將全部class文件、資源文件壓縮打成一個包(也能夠選擇不壓縮),可選擇在jar包中生成META-INF/MANIFEST.MF文件,MANIFEST.MF是清單文件,裏面能夠記錄主類、classpath等信息,供虛擬機使用。
接下來的一段時間裏,咱們將以如下路徑學習jar命令和清單文件的相關知識

    jar打包class文件
    帶包class文件jar打包
    清單文件的使用

在這篇文章裏咱們將使用簡單的java程序來熟悉jar命令的使用,由於是出於熟練使用jar的目的,下面的操做中可能會囉裏囉嗦、重複使用jar命令,如下是本片文章的目錄,精簡版直接看 jar命令的選項

            一 jar命令的選項
                用法
                選項
                本節中使用到的命令
            二 只有一個class文件的可執行jar的實現
                方法一將Mainjar所有解壓修改MANIFESTMF文件後再從新打包
                方法二生成jar包的時候爲其指定清單文件
                方法三爲jar包指定清單文件
                方法四爲jar更新文件文件是清單文件
            三 多個class的打包

一. jar命令的選項
用法:

大括號中的選項是必選的,中括號裏選項是可選的,jar-file是jar文件;manifest-file是清單文件,即jar包中的META-INF/MANIFEST.MF文件

jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...

    1

選項:

-c  (create)建立新檔案
-t  列出檔案目錄
-x  從檔案中提取指定的 (或全部) 文件
-u  (update)更新現有檔案
-v  在標準輸出中生成詳細輸出
-f  指定檔案文件名
-m  包含指定清單文件中的清單信息
-n  建立新檔案後執行 Pack200 規範化
-e  爲捆綁到可執行 jar 文件的獨立應用程序
    指定應用程序入口點
-0  僅存儲; 不使用任何 ZIP 壓縮
-P  保留文件名中的前導 '/' (絕對路徑) 和 ".." (父目錄) 組件
-M  不建立條目的清單文件
-i  爲指定的 jar 文件生成索引信息
-C  更改成指定的目錄幷包含如下文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

本節中使用到的命令

jar uf xx.jar [file … | path]是須要注意的,它在更新完jar文件後會生成新的清單文件,這一點在本篇文章的 「方法4:爲jar更新文件,文件是清單文件」 中有實例說明

jar cf xx.jar [file ... | path]  將file等文件或path目錄打包成xx.jar
jar cvf xx.jar [file ... | path]  同上,顯示詳細信息
jar cmf manifest-file xx.jar [file ... | path]  將file等文件或path目錄打包到xx.jar,並制定它的清單文件
jar cMf xx.jar [file ... | path]  將file等文件或path目錄打包到xx.jar,包中不生成清單文件
jar uf xx.jar [file ... | path]  將file等文件或目錄更新到xx.jar,務必注意!!!這個更新會從新生成清單文件
jar uMf xx.jar [file ... | path]  同上,但不會生成清單文件
jar umf manifest-file xx.jar {file ... | path}  將file等文件或path目錄更新到xx.jar
jar tf xx.jar  列出xx.jar中全部文件
jar xf xx.jar  把xx.jar中全部文件提取到當前目錄
jar xf xx.jar {file ...}  把xx.jar中file等文件提取到當前目錄

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

二. 只有一個class文件的可執行jar的實現

首先建立一個jarDemo文件夾,裏面放置咱們的測試類

mkdir jarDemo
cd jarDemo
touch Main.java

    1
    2
    3

在Main.java裏面添加咱們的hello world代碼,並javac編譯

public class Main{
    public static void main(String ... args){
        System.out.println("hello world");
    }
}

    1
    2
    3
    4
    5

javac Main.java

    1

而後將生成的Main.class打包,c選項是建立一個新的jar包,f是指定jar包的名字

jar cf Main.jar Main.class

    1

若是附加使用v選項,則會列出詳細的打包信息

jar cvf Main.jar Main.class

    1

咱們能夠經過t選項來查看生成的jar中的文件,輸出的內容也就是包目錄和包文件,能夠看到是默認生成MANIFEST.MF文件的

jar tf Main.jar

輸出:
META-INF/
META-INF/MANIFEST.MF
Main.class

    1
    2
    3
    4
    5
    6

固然咱們也能夠經過M選項不生成MANIFEST.MF文件,能夠看到包中只有Main.class一個文件

rm Main.jar
jar cMf Main.jar Main.class
jar tf Main.jar

輸出:
Main.class

    1
    2
    3
    4
    5
    6

雖然咱們已經將Main.class打包了,而且Main.class有main(String … args)入口方法,但是這個jar仍是不能執行,由於虛擬機並不知道這個包中的哪一個class中是有main方法的

java -jar Main.jar

輸出:
Main.jar中沒有主清單屬性

    1
    2
    3
    4

下面仍是恢復到有MANIFEST.MF文件的Main.jar包,咱們要將他解壓,在MANIFEST.MF中添加主類屬性
解壓jar包的方法有不少種,咱們解壓的目的是爲了查看默認生成的MANIFEST.MF文件,並作修改,最後生成一個可執行的jar包,由於咱們的目的是出於熟練使用jar命名,下面咱們將使用多個方法實現這個目標
方法一:將Main.jar所有解壓,修改MANIFEST.MF文件後再從新打包

由於jar解壓命令只能解壓到當前目錄,這樣會形成文件混亂,咱們新建一個uncompress文件夾,將Main.jar拷貝到這個文件夾後再解壓,能夠看到,jar包中全部文件,x選項是提出所有或指定文件,這個例子裏是提出所有文件,實際中能夠用f選項提出指定文件,好比 >> jar xf Main.jar META-INF/MANIFEST.MF

mkdir uncompress
cp Main.jar uncompress
cd uncompress
jar xf Main.jar
ls -RF

輸出:
META-INF/   Main.class  Main.jar

./META-INF:
MANIFEST.MF

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

打開META-INF/MANIFEST.MF文件,看到默認生成的清單文件很簡單,只有兩行

Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)

    1
    2

添加上添加上主類屬性,注意冒號後面必定要留一個空格,最後必定要多留一個換行符

Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)
Main-Class: Main

    1
    2
    3

而後使用再將uncompress中全部目錄、文件所有打包,注意先將原來的Main.jar刪除,最後就能夠運行這個新的有主類屬性的Main.jar啦

rm Main.jar
jar cMf Main.jar .
java -jar Main.jar

輸出:
hello world

    1
    2
    3
    4
    5
    6

注意上面這個jar命令使用的M選項是不生成清單,由於本來uncompress目錄裏就有,若是仍是使用jar cf命令,生成的清單和上面第一次打包生成清單的是同樣的,沒有Main-Class: Main主類

rm Main.jar
jar cf Main.jar .
java -jar Main.jar

輸出:
Main.jar中沒有主清單屬性

    1
    2
    3
    4
    5
    6

方法二:生成jar包的時候爲其指定清單文件

仍是那個方法一的uncompress目錄,咱們把META-INF下的MANIFEST.MF移到uncompress目錄下,刪除Main.jar,和META-INF目錄,讓uncompress中只有Main.class和MANIFEST.MF兩個文件,MANIFEST.MF是有主類屬性的清單文件

mv META-INF/MANIFEST .
rm Main.jar
rm -r META-INF
ls -RF

輸出:
MANIFEST.MF Main.class

    1
    2
    3
    4
    5
    6
    7

接下了指定清單文件,生成Main.jar,m選項能夠指定一個清單文件

jar cmf MANIFEST.MF Main.jar Main.class
java -jar Main.jar

輸出:
hello world

    1
    2
    3
    4
    5

方法三:爲jar包指定清單文件

還記得最先那個jardemo目錄裏的那個清單裏沒有主類的Main.jar嗎,咱們爲它更新有主類的清單文件
jardemo/uncompress目錄下的的MANIFEST.MF是有主類的,咱們把它移到jardemo目錄下

cd desktop/jardemo
mv uncompress/MANIFEST.MF .
rm -r uncompress
ls -RF

輸出:
MANIFEST.MF Main.class  Main.jar    Main.java

    1
    2
    3
    4
    5
    6
    7

使用u選項更新jar包,使用m選項指定清單文件,輸出了一些警告信息,由於新的清單文件和Main.jar包中原來的清單信息有兩個字段是重名的

jar -umf MANIFEST.MF Main.jar

輸出:
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Manifest-Version.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Created-By.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

再運行這個jar

java -jar Main.jar

輸出:
hello world

    1
    2
    3
    4

方法四:爲jar更新文件,文件是清單文件

使用這個方法主要是爲了再次熟悉一下u選項和理解包的概念
咱們在jardemo目錄裏刪除有主類清單的Main.jar,再次生成最先的MANIFEST.MF中沒有主類的Main.jar

jar cf Main.jar Main.class

    1

jar包中的MANIFEST.MF裏記錄了主類,而MANIFEST.MF只是jar包中的一個文件,咱們將Main.jar中沒有主類的MANIFEST.MF替換爲有主類的MANIFEST.MF和方法三是一樣的效果,首先要講有主類的MANIFEST.MF放在合適的路徑裏面,咱們以前看到jar包中的文件是放在META-INF目錄裏的,使用u來更新jar,注意須要使用M來忽視清單文件

mkdir META-INF
mv MANIFEST.MF META-INF
jar uMf Main.jar META-INF/MANIFEST.MF
java -jar Main.jar

輸出:
hello world

    1
    2
    3
    4
    5
    6
    7

三. 多個class的打包

上一節中,jarDemo目錄中有Main.java和有主類信息的清單文件MANIFEST.MF,咱們只保留這兩個個文件,其餘所有刪掉,而後新建一個Say.java文件

ls -RF

輸出:
META-INF/   Main.java   Say.java

./META-INF:
MANIFEST.MF

    1
    2
    3
    4
    5
    6
    7

在新建的Say.java:

public class Say{
    public static void say(String str){
        System.out.println("This is " + str);
    }
}

    1
    2
    3
    4
    5

修改Main.java文件,讓它調用Say類中的Say.say(…)方法

public class Main{
    public static void main(String ... args){
        System.out.println("hello world");
        Say.say("Charles");
    }
}

    1
    2
    3
    4
    5
    6

咱們編譯文件並打包,注意指定一個那個有主類屬性的MANIFEST.MF

javac *.java
jar cmf Main.jar META-INF/MANIFEST.MF Main.class Say.class
java -jar Main.jar

輸出:
hello world
This is Charlesjava

相關文章
相關標籤/搜索