在平時我們打包會將其打成Jar,那麼在其他平臺運行的時候就需要安裝jre來支持運行。
那麼實際上Java是可以打包成native平臺所屬類型的,例如:
- exe
- installer
- image
- msi
- dmg
- rpm
- deb
當然我在查閱了很多博客,及其官網的信息,
見到最多的是exe4j,但是看到有一些評論說,打包之後無法運行,而且我下載了exe4j之後是不能運行的。所以排除此選項。
除了exe4j呢還有,install4j,jwrapper等工具,但是他們都是收費的,所以也排除。
還有Java9的jaot
,早期版本的java14的jpackage
,java8的javapackager
在查閱的博客中有人提到了java9的jaot
,下載了java9,但是並沒有找到jaot
,考慮到常用版本是8,所以也排除了jaot
。
那麼只剩下java14的jpackage
和java8的javapackager
,這兩個我都有過實踐,效果幾乎一直,打出來的包大小也差不多(沒有對jre做過任何裁剪的情況下)。
最終選擇了Java8自帶的javapackager
這個工具。(但是遺憾的是,無法顯示控制檯的內容,建議使用日誌文件去代替。java14的jpackage
是可以指定是否顯示控制檯)
現在我們就來看看,如何將jar包打包成native形式的包。
準備內容
-
Inno Setup Compiler(Java8支持6版本以下的,不要下載6及其6以上的版本,否則無法打包成功)
-
wix(打包成msi必須下載,沒有下載
javapackager
會提示缺少wix) -
java8的環境
-
示例的jar程序(本文使用這個jar作爲示例,方便交流學習)
程序介紹
啓動程序之後,會在c盤創建一個名爲
我是測試文件.txt
的文件,每秒會給文件中寫入”休眠*秒“的字樣,直到10s之後程序運行結束,結尾會有寫入成功的字樣。(如果啓動之後沒有生成該文件,請在任務管理器找到該進程結束,然後以管理員身份運行該程序。)
讓我們開始第一個打包吧!
在此之前,默認您準備內容已經閱讀並且完成了。
-
進入你下載jar的包的文件夾,並且打開
powershell
-
輸入:
javapackager -deploy -native image -outdir cs -outfile cs -srcfiles pack.jar -appclass cn.qs.CS -name CS
-
你會在同級目錄找到一個叫
cs
的文件夾,進入cs,再進入bundles文件夾。找到cs.exe,用管理員身份運行。 -
進入C盤就能找到該程序生成的
我是測試文件.txt
的文件
至此,簡單的打包結束。
現在我們來看一下上面的命令代表什麼意思。
javapackager---java8自帶的打包程序
-deploy---用來構建目標機器的發行版本,簡單說就是打包成exe或者其他平臺的包,如果不帶任何參數,會生成一個基本的應用程序,不建議不帶任何參數
-native image---爲jar創建磁盤鏡像(可以將image替換爲其他的類型,例如exe,msi,deb,rpm)
-outdir cs---輸出目錄。
-outfile cs----輸出文件(不要帶後綴,比如cs.exe,就寫cs就行了)。
-srcfiles pack.jar---要打包的jar文件。
-appclass cn.qs.CS---jar文件的主類的全限定名。(注意是全限定名)
-name CS---啓動之後的應用名稱
更多的參數將會在文章最後附上。也可以直接輸入javapackager
來查看幫助,或者進入官網查看
來做一些定製吧
目標
- 修改應用圖標
- 修改應用說明(按照官網操作,指定了但是無效,可以忽略)
- 修改應用程序的供應商(vendor)
注意:因爲是控制檯程序呢,所以 標題,寬,高指定的話也沒什麼意義。所以我們在此就修改這兩個屬性就可以了。
我們開始定製吧
注意:測試過image的形式,描述(description)和說明(vendor)是無效的,在exe和msi形式下是可以的
-
在下載的jar的同級目錄,刪掉剛纔生成的cs文件夾。
-
重新執行命令:
javapackager -deploy -native exe -outdir cs -outfile cs -srcfiles pack.jar -appclass cn.qs.CS -name CS -description "測試的描述" -vendor "測試廠商" -Bicon=".\cs.ico"
-
現在我們就定義成功了。(可以自行看一下,是不是我們自定義的圖標,說明,供應商)
關於更多自定義的話請查閱官網(這些自定義的bundle參數在使用的時候要注意,-B加上參數名=值 例如 icon 使用的時候就是 -Bicon=“path”)
bundle參數說明
除了上述打包bundle參數之外呢,在介紹一些通用的bundle參數和windows的bubdle參數。
通用參數
- appVersion=version
應用的版本,例如:-BappVersion=1.0.1- classPath=path
類路徑相對於打包後應用的目錄(默認不用設置。)- icon=path
應用圖標的路徑,例如:-Bicon=".\cs.ico"- identifier
用於其他特定平臺的默認值。- jvmOptions=option
用來指定jvm參數,例如:-BjvmOptions=-Xmx128m -BjvmOptions=-Xms128m- jvmProperties=property=value
當程序運行的時候,這個參數會被傳入到jvm中,可以通過System.getProperty()來獲取,java -Dproperty 都可以使用,需要指定參數名和值,如果要傳遞多個請參考:-BjvmProperties=apiUserName=example -BjvmProperties=apiKey=abcdef1234567890- mainJar=filename
包含主類的jar文件的名稱,該文件名通常是從jar文件的mainfest中獲得,如果你使用javapackager命令,不用指定這個值- preferencesID=node
用來檢查用戶可覆蓋的jvm選項,被指定的選項在運行時作爲-Dapp.preferences.id
.參數傳給應用,這個參數需要和userJVMOptions一起使用。- runtime=path
Jdk或者jre的位置,如果使用系統默認的jre則不需要提供。例如:-Bruntime=- userJvmOptions=option=value
能被用戶覆蓋的jvm選項 java命令所使用的任何選項都是有效的,要傳入多個,請參考:
-BuserJvmOptions=-Xmx=128m -BuserJvmOptions=-Xms=128mwindows
copyright=string
應用的版本字符串,例如:2002-2020 Jetbrains s.r.o.licenseFile=path
最終用戶許可協議的位置(EULA),例如 -BlicenseFile=COPYINGmenuHit=boolean
標誌着是否在開始菜單或開始屏幕上安裝快捷方式,設置爲true來安裝快捷方式,默認是true 例如:-BmenuHint=true
shortcutHint=boolean
標誌着是否在桌面安裝快捷圖標,設置爲true表示安裝,默認是false。例如:-BshortcutHint=truesystemWide=boolean
標誌着應用程序是安裝在Programs Files中還是在UserData中,設置爲true安裝在Programs Files,默認爲falsewin.menuGroup=group
menuGroup只有在menuHint爲true的時候才生效,menuHint爲false這個參數會被忽略掉。vendor=value
也就是作者,可以是個人,組織,公司等。用於exe,或者registry metadata.
參數簡述
用法: javapackager -command [-options]
其中 command 爲以下項之一:
-createjar
打包程序根據其他參數生成 jar 檔案。
-deploy
打包程序根據其他參數生成 jnlp 和 html
文件。
-createbss
將 css 文件轉換爲二進制形式
-signJar
使用提供的證書爲 jar 文件簽名。
-makeall
將 compilation, createjar 和 deploy 步驟作爲一個調用執行,
在其中預定義大多數參數。源必須位於 "src"
文件夾中, 生成的文件 (jar, jnlp, html) 將放入 "dist"
文件夾中。此命令只能以最簡單方式配置, 並且
儘可能自動進行。
createjar 命令的選項包括:
-appclass <application class>
要執行的應用程序類的限定名稱。
-preloader <preloader class>
要執行的預加載器類的限定名稱。
-paramfile <file>
包含默認命名應用程序參數的屬性文件。
-argument arg
JNLP 文件的 <fx:argument> 元素中要放入的未命名
參數。
-classpath <files>
相關 jar 文件名列表。
-manifestAttrs <manifest attributes>
附加清單屬性列表。語法: "name1=value1,
name2=value2,name3=value3"。
-noembedlauncher
如果存在, 打包程序將不會向 jarfile 添加 JavaFX
啓動程序類。
-nocss2bin
在複製到 jar 之前, 打包程序不會將 CSS 文件轉換爲
二進制形式。
-runtimeversion <version>
所需 JavaFX 運行時的版本。
-outdir <dir>
要將輸出文件生成到的目錄的名稱。
-outfile <filename>
生成的文件的名稱 (不帶擴展名)。
-srcdir <dir>
待打包文件的基目錄。
-srcfiles <files>
srcdir 中的文件的列表。如果省略, 將對 srcdir (在
這種情況下是必需的參數) 中的所有文件進行打包。
deploy 命令的選項包括:
-title <title>
應用程序的標題。
-vendor <vendor>
應用程序的供應商。
-description <description>
應用程序的說明。
-appclass <application class>
要執行的應用程序類的限定名稱。
-preloader <preloader class>
要執行的預加載器類的限定名稱。
-paramfile <file>
包含默認命名應用程序參數的屬性文件。
-htmlparamfile <file>
包含所生成小應用程序參數的屬性文件。
-width <width>
應用程序的寬度。
-height <height>
應用程序的高度。
-native <type>
生成自包含的應用程序包 (如果可能)。
如果指定了類型, 則只創建此類型的包。
所支持類型的列表包括: installer, image, exe, msi, dmg, rpm 和 deb。
-name <name>
應用程序的名稱。
-embedjnlp
如果存在, 會將 jnlp 文件嵌入 html 文檔中。
-embedCertificates
如果存在, 會將證書嵌入 jnlp 文件中。
-allpermissions
如果存在, 應用程序將需要 jnlp 文件中的所有
安全權限。
-updatemode <updatemode>
設置 jnlp 文件的更新模式。
-isExtension
如果存在, srcfile 將被視爲擴展。
-callbacks
在生成的 HTML 中指定用戶回調方法。格式爲
"name1:value1,name2:value2,..."
-templateInFilename
html 模板文件的名稱。佔位符格式爲
#XXXX.YYYY(APPID)#
-templateOutFilename
要將已填充的模板寫入到的 html 文件的名稱。
-templateId
用於模板處理的應用程序的應用程序 ID。
-argument arg
JNLP 文件的 <fx:argument> 元素中要放入的未命名
參數。
-outdir <dir>
要將輸出文件生成到的目錄的名稱。
-outfile <filename>
生成的文件的名稱 (不帶擴展名)。
-srcdir <dir>
待打包文件的基目錄。
-srcfiles <files>
srcdir 中的文件的列表。如果省略, 將對 srcdir (在
這種情況下是必需的參數) 中的所有文件進行打包。
createbss 命令的選項包括:
-outdir <dir>
要將輸出文件生成到的目錄的名稱。
-srcdir <dir>
待打包文件的基目錄。
-srcfiles <files>
srcdir 中的文件的列表。如果省略, 將對 srcdir (在
這種情況下是必需的參數) 中的所有文件進行打包。
signJar 命令的選項包括:
-keyStore <file>
密鑰庫文件名。
-alias
密鑰的別名。
-storePass
用於檢查密鑰庫完整性或對密鑰庫取消鎖定的口令。
-keyPass
用於恢復密鑰的口令。
-storeType
密鑰庫類型, 默認值爲 "jks"。
-outdir <dir>
要將輸出文件生成到的目錄的名稱。
-srcdir <dir>
待簽名文件的基目錄。
-srcfiles <files>
srcdir 中的文件的列表。如果省略, 將對 srcdir (在
這種情況下是必需的參數) 中的所有文件進行打包。
makeAll 命令的選項包括:
-appclass <application class>
要執行的應用程序類的限定名稱。
-preloader <preloader class>
要執行的預加載器類的限定名稱。
-classpath <files>
相關 jar 文件名列表。
-name <name>
應用程序的名稱。
-width <width>
應用程序的寬度。
-height <height>
應用程序的高度。
-v 啓用詳細輸出。
示例用法:
--------------
javapackager -createjar -appclass package.ClassName
-srcdir classes -outdir out -outfile outjar -v
將類目錄的內容打包到 outjar.jar,
將應用程序類設置爲 package.ClassName。
javapackager -deploy -outdir outdir -outfile outfile -width 34 -height 43
-name AppName -appclass package.ClassName -v -srcdir compiled
在由 package.ClassName 類啓動且大小爲 34x43 的
應用程序 AppName 的 outdir 中生成
outfile.jnlp 和對應的 outfile.html 文件。
javapackager -makeall -appclass brickbreaker.Main -name BrickBreaker
-width 600 -height 600
此命令執行包含編譯在內的所有打包工作:
compile, createjar 和 deploy。
結語
經過這一番操作,其實應該對打包有一定的個人理解了。
也有的人提出創建一個bat來啓動java程序,好處不言而喻,但是也有弊端。例如:在任務管理器裏面顯示的進程是java進程,那麼如果有多個這樣的程序呢,就會導致分不清進程。而且需要依賴JRE。
那麼在這種打包方式中呢,存在很多弊端,例如,包體積太大,但是解決了上面的弊端問題,而且在java9中可以使用jlink來對jre進行裁剪,包體積會進一步縮小,個人更傾向於第二種打包方式,如何抉擇,請結合業務場景和需求。
關於javapackager打包相關的內容,請參考官網
遇到問題,請在下方評論留言。