使用Java命令列編譯和打包jar
背景:
原先測試一個OCR識別的介面為了方便呼叫,寫了一個main方法的java類,打成了jar包,在windows環境下用bat指令碼呼叫。bat指令碼中也就是利用java -jar去掉用,然後利用main方法的args陣列引數動態傳參,最後記一下輸出和錯誤。
java -jar testocr.jar param1 param2 param3 http://127.0.0.1/cxfServerX/ 1>>work.log 2>>err.txt
今天由於介面變動,這個main方法中的一個地方需要修改,也就是這個jar包需要重新打,最開始這個jar包是用myeclipse直接打的,並且在jar包裡也保留了java原始檔,總共就一個java檔案,其他都是一些依賴的jar包。因為檔案數量不多也不復雜,所以乾脆直接在cmd下用命令編譯打包。
使用JAVAC編譯:
-
找到上次打好的jar包testocr.jar,複製一下留作備份,然後解壓成目錄testocr
目錄結構:
testocr -com/ // 存放原始碼檔案 com/xxx/xxx.java -jar/ // 裡面是所有依賴的jar包檔案 -META-INF/ // 裡面有MANIFEST.MF檔案,描述jar檔案所依賴的檔案 .classpath // 描述專案引用的jar包 .project // 專案描述檔案
-
先修改原始碼檔案,進入到com/test/目錄下,修改TestOCR.java檔案
-
修改後要對原始檔進行編譯,先隨便試一下。
# 剛開始沒有指定編碼時報錯了中文亂碼,這裡就先加上了,其中 -encoding "UTF-8" 和-encoding UTF-8 加不加引號都可以 base$ javac -encoding UTF-8 TestOCR.java TestOCR.java:6: 錯誤: 程式包net.sf.json不存在 import net.sf.json.JSONObject; ^ TestOCR.java:8: 錯誤: 程式包org.apache.http不存在 import org.apache.http.HttpEntity; ^ TestOCR.java:9: 錯誤: 程式包org.apache.http.client.methods不存在 import org.apache.http.client.methods.CloseableHttpResponse; ^ TestOCR.java:10: 錯誤: 程式包org.apache.http.client.methods不存在 import org.apache.http.client.methods.HttpPost; ^ TestOCR.java:11: 錯誤: 程式包org.apache.http.entity不存在 import org.apache.http.entity.StringEntity; ... # 這個報錯是意料之中的,因為TestOCR.java中import了很多三方jar包,需要指定一下類路徑
-
指定依賴的三方jar包類路徑後執行
# 首先就是javac -cp 和 javac -classpath是一樣的,直接輸入javac在幫助命令中也可以看出來 ... -classpath <路徑> 指定查詢使用者類檔案和註釋處理程式的位置 -cp <路徑> 指定查詢使用者類檔案和註釋處理程式的位置 ... # 這裡我用相對路徑,TestOCR.java依賴的jar包都放在這個jar目錄下 base$ javac -encoding UTF-8 -cp ../../jar/ TestOCR.java TestOCR.java:6: 錯誤: 程式包net.sf.json不存在 import net.sf.json.JSONObject; ^ TestOCR.java:8: 錯誤: 程式包org.apache.http不存在 ... # 結果還是報錯 很明顯還是找不到依賴包 但是路徑確實是正確的 # 然後我去掉最後一個/ 執行 base$ javac -encoding UTF-8 -cp ../../jar TestOCR.java # 很遺憾還是報錯,然後我又嘗試一下使用*去匹配所有.jar字尾的檔案 base$ javac -encoding UTF-8 -cp ../../jar/*.jar TestOCR.java javac: 無效的標記: ../../jar/XmlSchema-1.4.3.jar 用法: javac <options> <source files> -help 用於列出可能的選項 # 這裡感覺好像是javac直接懟到 依賴的jar包上去了,所以直接報錯了,換一種寫法 base$ javac -encoding UTF-8 -cp ../../jar/* TestOCR.java javac: 無效的標記: ../../jar/XmlSchema-1.4.3.jar 用法: javac <options> <source files> -help 用於列出可能的選項 # 加個引號試試 base$ javac -encoding UTF-8 -cp "../../jar/*" TestOCR.java # 編譯正確,在TestOCR.java檔案的相同目錄下出現了TestOCR.class檔案 # 可以使用-d指定class檔案的生成路徑,並且會按java檔案的 package包名生成檔案目錄結構 base$ javac -encoding UTF-8 -cp "../../jar/*" -d . TestOCR.java # 加上-d . 後,就在當前目錄下生成了TestOCR.java的package包名結構的檔案目錄,並將TestOCR.class放在此目錄下
打JAR包
-
因為jar包剛開始是從Myeclipse中打好的,所以MANIFEST.MF都是有的,當時也是手動寫的,按照格式指定一下主類和依賴的包路徑,記得需要注意幾點:
-
這個Class-Path後面的路徑名稱太多了話不能寫到一行,寫很多到一行會報錯行太長,直接換行寫就行,但是換行時從第二行開始要先敲兩個空格,後面再換行也要先有兩個空格。
-
key: value,key之後跟冒號再跟空格,這點跟yaml很像,還有Class-Path中的多個jar包路徑之間也是用空格分隔的。
-
Class-Path寫完之後最後一定要有一個空行。
-
注意Class-Path的路徑和生成好的Jar包的路徑,這裡我寫的相對路徑,相當於打好的jar包和lib在同一目錄下,這樣才能找到依賴的jar包路徑。
testocr -testocr.jar // 打好的jar包 -lib/ // 裡面是所有依賴的jar包檔案
- MANIFEST.MF檔案,最後兩個引數是包密封用的,詳情參考大佬的部落格:META-INF/MANIFEST.MF檔案中Sealed頭的作用與含義
Manifest-Version: 1.0 Main-Class: com.test.TestOCR Class-Path: lib/commons-beanutils.jar lib/commons-collections-3.2.jar lib/commons-httpclient.jar lib/commons-io-2.2.jar lib/commons-lang-2.4.jar lib/commons-logging.jar Name: com/test/ Sealed: true
-
-
使用jar命令進行打包
# 看一下引數 base$ jar 用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ... 選項: -c 建立新檔案 -t 列出檔案目錄 -x 從檔案中提取指定的 (或所有) 檔案 -u 更新現有檔案 -v 在標準輸出中生成詳細輸出 -f 指定檔案檔名 -m 包含指定清單檔案中的清單資訊 -n 建立新檔案後執行 Pack200 規範化 -e 為捆綁到可執行 jar 檔案的獨立應用程式 指定應用程式入口點 -0 僅儲存; 不使用任何 ZIP 壓縮 -P 保留檔名中的前導 '/' (絕對路徑) 和 ".." (父目錄) 元件 -M 不建立條目的清單檔案 -i 為指定的 jar 檔案生成索引資訊 -C 更改為指定的目錄幷包含以下檔案 如果任何檔案為目錄, 則對其進行遞迴處理。 清單檔名, 檔案檔名和入口點名稱的指定順序 與 'm', 'f' 和 'e' 標記的指定順序相同。 示例 1: 將兩個類檔案歸檔到一個名為 classes.jar 的檔案中: jar cvf classes.jar Foo.class Bar.class 示例 2: 使用現有的清單檔案 'mymanifest' 並 將 foo/ 目錄中的所有檔案歸檔到 'classes.jar' 中: jar cvfm classes.jar mymanifest -C foo/ . # 使用描述清單將當前目錄下所有檔案打包成 testocr.jar base$ jar -cvfm testocr.jar META-INF/MANIFEST.MF * 已新增清單 正在忽略條目META-INF/ 正在忽略條目META-INF/MANIFEST.MF 正在新增: META-INF/REFACTORINGS.XML(輸入 = 64) (輸出 = 52)(壓縮了 18%) 正在新增: com/(輸入 = 0) (輸出 = 0)(儲存了 0%) 正在新增: com/test/(輸入 = 0) (輸出 = 0)(儲存了 0%) 正在新增: com/test/TestOCR.java(輸入 = 4309) (輸出 = 1816)(壓縮了 57%) 正在新增: com/test/TestOCR.class(輸入 = 3420) (輸出 = 1841)(壓縮了 46%) 正在新增: jar/(輸入 = 0) (輸出 = 0)(儲存了 0%) ... # 使用 jar -tf testocr.jar 檢視一下jar包內的檔案 base$ jar -tf testocr.jar META-INF/ META-INF/MANIFEST.MF META-INF/REFACTORINGS.XML com/ com/test/ com/test/TestOCR.java com/test/TestOCR.class jar/ jar/spring-context-2.0.8.jar jar/json.jar ... # 檢查後沒有問題 可以使用了,最後執行就java -jar testocr.jar即可,已經用bat指令碼寫好了互動,完成
總結:
使用這些命令處理一些簡單的類還是很方便的,對於複雜的還是使用開發工具去搞比較合適。
-