21

解锁Java打包新姿势

 4 years ago
source link: https://juejin.im/post/5e2eba31e51d4558864b1b29
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

解锁Java打包新姿势

在平时我们打包会将其打成Jar,那么在其他平台运行的时候就需要安装jre来支持运行。

那么实际上Java是可以打包成native平台所属类型的,例如:

  • installer
  • image

当然我在查阅了很多博客,及其官网的信息,

见到最多的是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之后程序运行结束,结尾会有写入成功的字样。(如果启动之后没有生成该文件,请在任务管理器找到该进程结束,然后以管理员身份运行该程序。)

让我们开始第一个打包吧!

在此之前,默认您准备内容已经阅读并且完成了。

  1. 进入你下载jar的包的文件夹,并且打开powershell

  2. javapackager -deploy -native image  -outdir cs -outfile cs -srcfiles pack.jar -appclass cn.qs.CS -name CS
    复制代码
  3. 你会在同级目录找到一个叫cs的文件夹,进入cs,再进入bundles文件夹。找到cs.exe,用管理员身份运行。

  4. 进入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来查看帮助,或者进入官网查看

来做一些定制吧

  1. 修改应用图标
  2. 修改应用说明(按照官网操作,指定了但是无效,可以忽略)
  3. 修改应用程序的供应商(vendor)

注意:因为是控制台程序呢,所以 标题,宽,高指定的话也没什么意义。所以我们在此就修改这两个属性就可以了。

我们开始定制吧

注意:测试过image的形式,描述(description)和说明(vendor)是无效的,在exe和msi形式下是可以的

  1. 在下载的jar的同级目录,删掉刚才生成的cs文件夹。

  2. 重新执行命令:

    javapackager -deploy -native exe  -outdir cs -outfile cs -srcfiles pack.jar -appclass cn.qs.CS -name CS -description "测试的描述" -vendor "测试厂商" -Bicon=".\cs.ico"
    复制代码
  3. 现在我们就定义成功了。(可以自行看一下,是不是我们自定义的图标,说明,供应商) 关于更多自定义的话请查阅官网(这些自定义的bundle参数在使用的时候要注意,-B加上参数名=值 例如 icon 使用的时候就是 -Bicon=“path”)

bundle参数说明

除了上述打包bundle参数之外呢,在介绍一些通用的bundle参数和windows的bubdle参数。

通用参数

  1. appVersion=version 应用的版本,例如:-BappVersion=1.0.1
  2. classPath=path 类路径相对于打包后应用的目录(默认不用设置。)
  3. icon=path 应用图标的路径,例如:-Bicon=".\cs.ico"
  4. identifier 用于其他特定平台的默认值。
  5. jvmOptions=option 用来指定jvm参数,例如:-BjvmOptions=-Xmx128m -BjvmOptions=-Xms128m
  6. jvmProperties=property=value 当程序运行的时候,这个参数会被传入到jvm中,可以通过System.getProperty()来获取,java -Dproperty 都可以使用,需要指定参数名和值,如果要传递多个请参考:-BjvmProperties=apiUserName=example -BjvmProperties=apiKey=abcdef1234567890
  7. mainJar=filename 包含主类的jar文件的名称,该文件名通常是从jar文件的mainfest中获得,如果你使用javapackager命令,不用指定这个值
  8. preferencesID=node 用来检查用户可覆盖的jvm选项,被指定的选项在运行时作为 -Dapp.preferences.id.参数传给应用,这个参数需要和userJVMOptions一起使用。
  9. runtime=path Jdk或者jre的位置,如果使用系统默认的jre则不需要提供。例如:-Bruntime=
  10. userJvmOptions=option=value 能被用户覆盖的jvm选项 java命令所使用的任何选项都是有效的,要传入多个,请参考: -BuserJvmOptions=-Xmx=128m -BuserJvmOptions=-Xms=128m

windows

  1. copyright=string 应用的版本字符串,例如:2002-2020 Jetbrains s.r.o.

  2. licenseFile=path 最终用户许可协议的位置(EULA),例如 -BlicenseFile=COPYING

  3. menuHit=boolean

    标志着是否在开始菜单或开始屏幕上安装快捷方式,设置为true来安装快捷方式,默认是true 例如:-BmenuHint=true

  4. shortcutHint=boolean 标志着是否在桌面安装快捷图标,设置为true表示安装,默认是false。例如:-BshortcutHint=true

  5. systemWide=boolean 标志着应用程序是安装在Programs Files中还是在UserData中,设置为true安装在Programs Files,默认为false

  6. win.menuGroup=group menuGroup只有在menuHint为true的时候才生效,menuHint为false这个参数会被忽略掉。

  7. 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打包相关的内容,请参考官网

遇到问题,请在下方评论留言。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK