将JRE嵌入Windows可执行文件?

70
假设我想分发一个Java应用程序。
如果我想将其作为单个可执行文件分发,我可以很容易地构建一个.jar文件,其中包含应用程序及其所有外部依赖项(通过一些Ant技巧)。
现在假设我想将其作为Windows上的.exe文件分发。鉴于存在诸如Launch4j之类的好工具,这很容易。
但是,如果我也不想依赖终端用户安装正确的JRE(或者根本没有安装任何JRE),该怎么办?我想分发一个带有我的应用程序的JRE,而且我的应用程序应该在这个JRE上运行。创建Windows安装程序可执行文件并嵌入一个包含所有必要JRE文件的文件夹很容易。但是那样我就在分发一个安装程序而不是单个文件的应用程序。
是否有一种方法可以将应用程序和JRE都嵌入到.exe文件中,使其充当应用程序启动器(而不是安装程序)呢?

15
常规应用程序通过安装程序或独立可执行文件的方式将永远存在。有很多原因使得基于网络的部署并不是一种适用于所有情况的解决方案。 - SnakeDoc
@SnakeDoc的链接已经失效了。exe4j可能已经更名为install4j?请访问http://www.ej-technologies.com/products/install4j/overview.html。 - akauppi
@akauppi 这是一个更新后的链接:http://www.ej-technologies.com/download/exe4j/files - SnakeDoc
@akauppi Install4j可以构建一个带有安装向导的安装程序,并且可以完成许多任务。exe4j则可以构建一个.exe文件,您可以直接启动应用程序而无需进行安装(类似于Minecraft.exe)。 - SnakeDoc
感谢澄清。即便如此,该链接已经过时。现在应该使用:https://www.ej-technologies.com/download/exe4j/files(注意:需要商业许可证)。 - akauppi
13个回答

24

尝试使用AvianProGuard工具包。 Avian允许在您的应用程序中嵌入轻量级虚拟机。支持Linux、MacOS、Windows和iOS。而ProGuard则允许您缩小大型JAR文件以准备嵌入。


17

3
Packr可以正常工作,但它会创建一个包含jre/文件夹、app.exe和原始app.jar的文件夹结构。您仍然需要创建一个安装程序,将此文件夹结构复制到C:\Programs\文件夹中。此外,您的.jar文件仍然存在,它没有嵌入到.exe文件中。除此之外,这是一个不错的工具。 - sarah.ferguson
你找到更好的工具来生成单个可执行文件了吗? - jhagege
请查看我的答案,它可以创建一个单独的可执行文件。 - Gabriel H

7

Excelsior JET 看起来有点有趣。会仔细看看它。恐怕我不太相信GCJ,但我可以试一试。关于 VMKit,CLI 的 JRE 实现是否需要 .NET? - perp
VMKit是一个同时支持.net和JVM编译的解决方案,对于JVM方面,它似乎与GNU Classpath合并;但目前仍处于测试阶段,因此我认为它在商业使用方面还有些不足。(我唯一发现的限制是Excelsior JET不支持MacOSX。) - metismo
我们提供免费的Excelsior JET许可证,供非商业用途使用,以防万一:http://www.excelsior-usa.com/jetfree.html - Dmitry Leskov
VMKit项目已经停止维护。 - Furetto

6

在我自己遇到这个问题后 -

1)创建一个包含您应用程序jar文件的文件夹

2)创建一个包含jre的子文件夹

3)创建一个批处理文件,在应用程序使用期间覆盖环境变量,并启动您的应用程序:

REM requiered so java wont run into issues with an installed version if one exists
SETLOCAL ENABLEEXTENSIONS
SET JAVA_HOME="./jre"
"./jre/bin/java.exe" -jar "applicationName.jar"
pause

4)使用.bat转.exe转换器,选项包括:https://listoffreeware.com/6-best-free-bat-exe-converter-software-windows/

第一个选项在此处可用:

https://web.archive.org/web/20190305143030/http://www.f2ko.de/downloads/Bat_To_Exe_Converter.zip

5)创建一个包含文件夹并在运行时运行.bat文件的exe


4
有没有一种方法可以将应用程序和JRE嵌入到一个.exe文件中,作为应用程序启动器(而不是安装程序)?
如果您愿意使用商业工具,install4j 可以非常顺利地解决这个问题(请参见其"Features" page)。它可以生成同时应用程序启动器和安装程序。
我不想重复太多,所以请查看例如this earlier answer,在其中我推荐了它(作为安装程序构建器,但在这里没有太大区别)。
总结/底线:install4j可以创建本机的.exe启动器,绝对不依赖于预安装的JRE(或任何其他特定库),并且它提供了灵活的选项来打包(和检测)JRE。

我已经下载了试用版,但是我真的不知道如何让它做我想要的事情。我只能让它创建一个安装程序? - perp
我刚刚意识到,install4j背后的公司还有一个名为exe4j的产品,专门用于创建启动器:http://www.ej-technologies.com/products/exe4j/overview.html。 我现在不确定exe4j是否可以做一些install4j不能做的事情 - 据我所知,两者都可以创建带有捆绑JRE的exe启动器。 - Jonik
@Jonik,install4j是用于创建捆绑了嵌入式JRE(或使用系统JRE)的exe文件来安装Java应用程序。exe4j则构建一个独立的exe文件,并捆绑了JRE或使用系统JRE,无需安装即可运行...就像著名的Minecraft.exe启动器一样,不需要安装...只需双击即可使用。 - SnakeDoc

3

2
Netbeans会自动创建一个安装程序,使用必需的Innosetup和Wix,这些必须单独安装。启动安装程序后,它会创建一个文件夹结构,其中包含一个runtime/文件夹、一个app.exe文件和一个app/文件夹,您的原始app.jar位于C:\User\AppData\Local文件夹中,并创建相应的开始菜单。请注意,您的.jar文件仍然存在,而不是嵌入在.exe文件中。 - sarah.ferguson


1
我知道我来晚了,不过看起来ej-technologies(喜欢他们的东西)有一个新的解决方案叫做exe4j,可以完全按照OP的要求实现,而无需任何有趣的业务。

http://www.ej-technologies.com/products/exe4j/overview.html

如果你正在开源项目中工作,他们会提供免费的许可证(只需联系他们即可)。如果是商业项目,则需要许可证...但以69美元的价格购买许可证非常便宜且值得购买。
从他们的网站上可以看到:
If you want your own process name instead of java.exe in the task manager
and a user friendly task-bar grouping, exe4j does the job for you.

exe4j helps you with starting your Java applications in a safe way, displaying
native splash screens, detecting or distributing suitable JREs and JDKs,
startup error handling and much more.

1
我编写了一个解决方案,具有以下特点:
  • 它只编译成一个小的exe文件(30 kb),只调用jre
  • 你只需要从一个独立的cpp文件编译一次exe(你需要修改cpp文件,将“com.example.MyApplication”替换为你自己的类名)
  • 选择一个图标,它会被嵌入exe文件中
  • 完成的exe文件现在是你的Java启动器,它会捕获任何java.exe的错误,并在启动失败时显示信息对话框
  • 没有控制台窗口

由于exe文件非常小,你可以构建它一次并将其放入存储库。除非你重命名主Java类或想要更改图标,否则不需要更新它。

你部署的应用程序可能看起来像这样:

app_root/
    myapp.exe        # the launcher created by this project
    jre/             # the bundled JRE, created by jlink
    lib/
        MyApp.jar    # your Java application
        ...          # any third-party libraries, etc.

你可以在这里查看: https://github.com/foolo/windows-jre-laucher

0
根据文档,JSmooth可以做到这一点。我只尝试过没有嵌入JRE的情况,但非常满意。它可以通过ant进行脚本编写,并且我们在Linux上构建。

http://jsmooth.sourceforge.net/features.php


它在哪里说了?我浏览了一下,只看到提到它支持“捆绑”JRE,这不是同一件事。关于这个问题,我所能看到的只有手册中3.4.2节提到的内容... - perp
有时将JRE与应用程序捆绑在一起更加方便。 JSmooth也可以处理这个问题,您只需要定义JRE期望在哪个文件夹中即可。如果JRE不在应该在的位置,它会很好地回退到标准JVM搜索。我认为这是指未安装的JRE。 - Thorbjørn Ravn Andersen
2
是的,没错,.exe 文件可以在指定文件夹中查找 JRE,但我已经知道有几个不同的工具可以实现这一点。我想知道是否有一种解决方案,可以将 JRE 嵌入到应用程序二进制文件本身中,这是不同的。所以不是“捆绑”,而是“嵌入”。 :-) - perp
请查看此问题并在JSMOOTH的情况下给我一个解决方案 http://stackoverflow.com/questions/5407178/problem-in-bundling-jre-in-jsmooth-in-java - Venky
@venka,我自己没有尝试过嵌入式用例,并且我发现服务启动器不能很好地工作。如果你不能轻松地使它工作并且作者没有回应,我建议使用另一个启动器。 - Thorbjørn Ravn Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接