让 Java 再次伟大,没有人比我更懂得如何打包!(分享一个四两拨千斤的多 jar 打包 exe 方式)

6 月 29 日
 ko1haha

Java 确实是内存不高效的。同样的内存,fultter / dart 能够创建流畅的应用,而 Java 要么卡成 ppt ,要么疯狂吃内存。

分享测试一个虚拟机内存回收效率的方法(大家应该都会吧:):win 下使用 procgov 假装本机只有 100 mb 内存,再运行 gui 程序,测试卡不卡。

结果,javafx 卡成 ppt ,flutter 写的桌面 app 却依然流畅,几乎没有卡顿!(例子:dart 写的 myune_music 存在严重的内存泄漏,稍微切换内存狂飙 300mb+,然而限制 100mb 后,依然流畅,神奇吧!)

这说明 flutter / dart 的虚拟机比 java 更高级 —— 即使再内存泄露的情况下。

人才不断涌入新的领域,Java 已经成熟到可以封印起来装裱,成熟到可以使用 java8 一万年,新的改进似乎九牛一毛,再也不能从根本上提升。

但当我从 64 位的 java8 切换到 32 位的 java8 ,内存需求立马减半,即使限制 100mb 内存,也没有那么卡了。

这给我一点信心。我还是很喜欢 javafx ,也曾升级到新的 open jdk ,打包方式太复杂,而且几乎没有区别,尤其是浏览器内核,所以又回到 java8 并锁死。

那么,如何打包分享给其他用户呢?

搜遍全网,似乎没有好的方案?

这些方案的本质是启动器。因为 java 程序的本质就是调用上位开发者提供的虚拟机.exe 运行编译后的字节码。

那我自己写个启动器好了!编不了虚拟机,我还编不了启动器?小样,何须他人预制!

先说我自己如何自用一些 java 小工具的:使用 idea 编译后,写个 bat/AHK/Python 调用 java.exe 运行编译好的 class 。

那么我的启动器就可以封装这条启动指令。

图像( AHK 写的启动器 GUI ):

没有检测到 jvm 的时候,提供下载链接。启动成功后,保存快捷方式,就能直接运行 javaw.exe ,不再需要启动器,干掉中间层!

别人还在研究怎么使用他人预制的启动器.exe ,我已经干掉启动器了,启动器就是个跳板,用于导出快捷方式,也可以右键固定开始菜单,几乎没啥问题!

就用这个方法发布些小工具吧,让 Java 再次伟大,从占领小工具 && 小游戏开始!

4831 次点击
所在节点    Java
47 条回复
kestrelBright
6 月 29 日
没有无用的工具 总有适合的人
ko1haha
6 月 29 日
@mmdsun Native 打包应该不是纯 Java Jvm 了,应该有所牺牲,不知性能如何。还是那句话,没有一个可以快速测试的例程.exe ,还是要苦哈哈打开 idea,然后不断往我 c 盘下载一些东西,性能仍是个谜。。
ruanimal
6 月 29 日
得配一下 TLP ( The Linux Power Manager )是 Linux 上最受欢迎的高级电源管理工具之一
0x64
6 月 29 日
你们 j8 确实厉害,佩服佩服
sheeta
6 月 29 日
试试用 openj9 jvm 看看,内存应该还能降
zhangshaohan
6 月 29 日
@ko1haha #17 我用的原生 QT
jinwiforz
6 月 29 日
java 真难受
5had0w
6 月 29 日
graalvm 打包 exe 不会很大,直接可以运行,不需要 java 环境
ko1haha
6 月 29 日
@mmdsun 刚刚试了,电脑里就有个 GraalVm ,找出来 bin/native-image.cmd ,然后转换一个 100kb 的 jar 为 native exe 。cpu 狂飙 100 ,然后生成一个 19 mb 的 exe ,这道没什么,关键不能运行,读取参数错误,存在兼容性问题。

doc : https://www.graalvm.org/latest/reference-manual/native-image/guides/build-native-executable-from-jar/

测试的是 ManifestEditor.jar : https://github.com/WindySha/ManifestEditor

说白了,这玩意儿就是给服务器省带宽用的,不是给普通人开发应用程序用的。使用 native-image 在编译时需要更多的计算机资源,以及更多的测试精力,去处理各种各样的兼容性问题。。

总之:长远看 graalvm 能给大公司省钱,就是周期不知道有多长。。
HTravel
6 月 29 日
@ko1haha Java 程序打包成 exe ,这都 20 多年前的老问题了,算什么没人提的思路。我给你一个 win32ASM 汇编完整版的思路,我自己都用十几年了:
1 、检测并自动安装私有 JRE ,不影响用户计算机上的 JRE 环境。原理:先安装一遍 JRE ,然后用 InnoSetup 将安装目录制作成私有 JRE 的 exe 安装包,私有 JRE 的本质,就是安装目录、注册表信息都放在另一个路径下即可。

2 、将上述私有 JRE exe 安装包作为启动器 exe 文件的一个资源项,也可以放在公网或内网,然后引用该连接。

3 、这个启动器用 win32ASM 汇编写,检测私有 JRE 是否已安装,没有就从自己资源项释放并静默安装,或从配置文件中所写的 URL 下载并静默安装。然后根据配置文件所写的参数格式,组织用户通过命令行或 Explorer 传递过来的各参数,以 CreateProgress 的方式调用 java.exe 或 javaw.exe ( GUI 程序)即可。甚至还有进程内的方案,就是用 LoadLibrary 调用 jvm.dll
lesismal
6 月 29 日
> 总之:长远看 graalvm 能给大公司省钱,就是周期不知道有多长。。

别人换 golang 、rust 、zig 了,java 这种该淘汰就淘汰吧,淘汰了就省钱了,但历史业务积累太多,所以如 OP 所说:“就是周期不知道有多长。。”
ashuai
6 月 29 日
java 生态一般不搞 all in one 吧,微服务的话,一个个换就行了,其实就是想不想的问题
huyangq
6 月 29 日
额 java 自带的就可以打包 javafx
就是 jlink+jpackage
sir283
6 月 30 日
exe ?那我为什么不选择 c#+winform ? c#好歹是微软亲儿子,而且从 Windows8 开始,系统直接内置了,编译出来的程序体积也很小,比 Java 好多了,c#甚至能几乎无损直接调用 C/C++的库,也比 Java 方便的多。
a0210077
6 月 30 日
老项目 java8 继续呆着,新项目建议至少上 java17 ,激进点 java25 有虚拟线程

"没有检测到 jvm 的时候,提供下载链接。启动成功后,保存快捷方式,就能直接运行 javaw.exe ,不再需要启动器,干掉中间层!"
公司内部用跑过去装个 JRE ,生产环境"提供下载链接"有点过分了,但本质还是装了个 JRE 而不是"干掉中间层"

"就用这个方法发布些小工具吧,让 Java 再次伟大,从占领小工具 && 小游戏开始!"
小工具写 bat/ps1/python 脚本都比 JAVA 来得轻量,GUI 界面不是 JAVA 擅长的领域(内置界面丑),小游戏有 h5 游戏引擎有浏览器就能玩。恐怕 OP 的美梦要破灭了
alexluo1
6 月 30 日
老 j8 这么难杀吗
keenkiller
6 月 30 日
2026 年了,用 AI 把你写的东西翻译成 QT 就完事
msg7086
6 月 30 日
#18 连 Oracle 都已经在往 JDK25 迁移了,你还死抱着 8 啊。
ko1haha
6 月 30 日
@HTravel 我表达的思路根本就不是如何写启动器,别来显摆你会汇编,而且无图,说谁都会。我的思路是写个启动器,然后用启动器创建方式啊,这之前根本没人提。
ko1haha
6 月 30 日
@a0210077 Javafx 不丑。"干掉中间层"你没理解我意思,中间层的意思是第三方的启动器 wrapper ,启动器是个 exe ,结果启动的是 java.exe ,中间层是这个意思懂了吧。

不过也有 wrapper 本身就是 jre ,比如 WinRun4J 。

还有内网"提供下载链接"怎么就过分了?实在不行你可以用 U 盘拷贝安装包。

bat/ps1/python 写的小工具只能自用吧,部署到自己的另外一台电脑都成问题。小游戏确实 h5 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1223686

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX