jar文件打包成app

在Mac上运行jar文件(例如Behinder)每次都需要

1
java -XstartOnFirstThread -jar Behinder.jar 

,感觉太繁琐了。因此,想打包成app方便使用。成功打包效果图如下,这里给大家提供打包出来的app。

链接:https://pan.baidu.com/s/1474CrgbbSfbXxqJGg9carA 密码:f9vm

成功效果图

使用工具可方便的将jar文件打包成app,本文以Behinder为例,记录所遇到的问题以及如何处理。

前期准备

下载jar2app之后,将其安装。

1
2
3
4
5
6
7
8
9
10
# Install
git clone https://github.com/Jorl17/jar2app
cd jar2app
chmod +x install.sh uninstall.sh
sudo ./install.sh
# Install to /usr/local/bin
git clone https://github.com/Jorl17/jar2app
cd jar2app
chmod +x install.sh uninstall.sh
sudo ./install.sh /usr/local/bin

生成APP

通过jar2app的命令我们可以得知,直接使用对应命令即可生成。其中需要注意以下两点:

  1. Behinder需要通过-XstartOnFirstThread命令启动;
  2. Behinder需要jre6~jre8版本才可以运行。

因此我在使用jar2app时,指定了JVM设置和JDK版本。

1
jar2app Behinder.jar -j "-XstartOnFirstThread" -r /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk

使用上面的命令可以成功生成一个app,但是直接运行无法打开。

问题排查

直接打开Behinder.app/Contents/MacOS/JavaAppLauncher启动脚本,提示数据库文件丢失,无法启动。

数据库文件丢失

数据库文件丢失

根据报错信息提示以及Behinder本身的文件结构,我将data.db移动到Behinder.app/Contents和其他杂七杂八的位置都不行。

1
2
3
4
5
6
Contents/data.db
Contents/Java/data.db
Contents/MacOS/data.db
Contents/Plugins/jdk1.8.0_181.jdk/Contents/data.db
Contents/Plugins/jdk1.8.0_181.jdk/Contents/MacOS/data.db
Contents/Resources/data.db

重构class文件

根据报错信息(数据库文件丢失)以及上述所进行的测试方法,基于当前的情况,只能通过将jar包文件反编译成class文件进行查看,判断本身源码逻辑。这里我采用JD进行反编译,直接加载Behinder的jar包文件。根据关键字:data.db进行搜索。

源代码查询

根据上图可以看到对应判断的逻辑在:net/rebeyond/behinder/core/ShellManager.class文件中:

1
2
3
if (!new File("data.db").exists()) {
throw new Exception("数据库文件丢失,无法启动。");
}

通过File().exists()进行判断文件是否存在,根据大佬的提示得知File().exists()使用的user.home作为路径,将其修改成File.getAbsoluteFile()即可成功。

测试代码

测试结果

在JD将ShellManager.class保存成java代码,使用Intellij创建一个项目。Ps:也可以用eclipse等。

这里我新建了一个Maven项目,Project SDK选择1.8.0

Project SDK

下面有关字段全部设置成Behinder

GroupId

ProjectName

将ShellManager.java文件拖入到src/main/java目录下,并将File().exists()修改成File().getAbsoluteFile().exists()。

修改代码

新建一个package,右键java目录new即可创建,目录名称为net.rebeyond.behinder.core。该名称来源为ShellManager在Behinder.jar文件中的路径。将ShellManager.java文件移动到net.rebeyond.behinder.core中。

新目录结构

此时还有一系列包引入问题待解决,这时候点击【File】选项中的【Project Structure】功能,在【Project Settings】中的【Modules】的【Dependencies】中引入Behinder.jar文件。

Project Structure

这时候还存在模块无法import的问题,根据查看发现是json模块无法引入,查看JD中json包是20180130的。在jar-download页面进行下载即可,下载完成之后,按照刚刚的流程导入。导入完成之后,这时候已经所有包都正常import。

import success

使用【Build Project】将java文件编译成class文件。

BuildProject

解压Behinder.jar文件,将解压出来的ShellManager.class文件替换成新编译出来的ShellManager.class文件。替换完成之后,使用压缩软件将其压缩成zip。将文件后缀修改成jar,在终端下运行,看能否成功运行。Ps:记得在Behinder.jar文件同级目录需要有一个data.db;这里有个问题,我用BetterZip将其压缩成zip之后,修改后缀无法运行,使用BandiZip(Windows)压缩可以,猜测有可能是软件压缩机制或者操作系统的问题。也可以使用jar命令进行打包。

1
jar -cfm Behinder.jar ./META-INF/MANIFEST.MF ./*
1
java -XstartOnFirstThread -jar Behinder.jar

运行成功

可以成功运行,在使用jar2app命令将其打包成app

1
jar2app Behinder.jar -j "-XstartOnFirstThread" -r /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk

将data.db文件移动到Behinder.app/Contents即可成功运行。

生成带有图标的APP

上面生成的app是没有图标的,jar2app有-i参数支持图标生成。直接将Behinder.jar文件的net/rebeyond/behinder/resource目录下的logo.jpg拿出来。使用ICON在线转换,这里需要注意的是下载的文件格式应该为icns,并非是icon。

使用如下命令即可生成一个带有logo图标的Behinder.app文件。

1
jar2app Behinder.jar -j "-XstartOnFirstThread" -r /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk -i logo.icns

总结

这里面踩了无数个坑,反反复复好长一段时间才解决。

  1. 工具记得多读手册,例如在这里用的jar2app直接在GitHub上面多读手册,基本问题都能解决;
  2. 实现同样功能的不同函数,在使用时需要按照需求进行使用。例如这里的File().exists()与File.getAbsoluteFile(),不同函数名总有会不一样的地方,直接平时只是为了实现功能而忽略其本质,有时候出现问题的时候需要深入了解其本质;
  3. 在处理问题过程中使用到软件工具出现问题时,可不进行任何修改重复使用软件进行问题定位。例如这里的BetterZip压缩之后无法运行,我是通过直接解压缩-压缩-运行将这个问题定位出来的。