如何将动态JVM命令行标志传递给自包含的JavaFX应用程序?

时间:2015-06-12 17:52:55

标签: java deployment javafx jvm

编辑:Oracle接受我的错误报告,要求增强为JDK-8138944 : Support command line arguments to the JVM passed to self-contained app launchers

问题

我的团队正在开发一个开源Java SE项目ImageJ,该项目目前有一个custom native launcher在跨平台C中编写。我们希望远离此启动器,切换到更现代化,行业标准和可维护的部署机制。 JavaFX self-contained applications是迄今为止我们发现的最有希望的解决方案。

ImageJ当前的本机启动器的一个重要功能是它能够自定义JVM的启动方式。例如,您可以写:

ImageJ --debugger=8000 myFile.png

启动程序将使用标志:

调用JVM
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:8000

同时将myFile.png作为Java主类的参数。

但是从文档中,我们看不到用JavaFX打包工具完成类似工作的方法。

考虑

我知道UserJvmOptionsService提供了一种配置JVM启动方式的方法(通过内部的Java Preferences API,JavaFX启动程序在JVM启动之前读取)。这对于为用户提供友好的对话框非常有用,他们可以调整最大堆大小和其他常用参数。当然,我们可以将远程调试切换和端口设置添加到这样的对话框中,和/或通过CLI支持JVM配置 - 但是它需要重新启动应用程序。

理想情况下,我们根本不需要支持这种情况,而是在Java启动JVM启动后处理所有命令行参数。例如,在大多数情况下,只要在应用程序的启动周期中尽早完成,就可以通过简单地解析arg并在运行时设置系统属性来支持形式-Dfoo=bar的系统属性。 。但很明显,很多情况下,在JVM启动之后这样做太晚了:

我们的用户希望能够在CLI上传递这些设置,并使Java运行时相应地运行 - 对于ImageJ,它对于向后兼容性尤为重要。

可能的解决方案

  • 我们可以保留本机C启动程序,替换Java打包工具安装的本机可执行文件。但这让我觉得非常脆弱,并且在很大程度上违背了切换到JavaFX部署的目的,因为我们仍然需要在几个不同平台上维护,构建和测试自定义本机启动器。

  • 或者,我们可以让应用程序主类成为一个非常精简的CLI选项解析器,然后生成JVM的第二个实例。这将使引导逻辑保持在纯Java中,这将比当前本机C代码更易于维护,同时充分利用JavaFX部署方案的跨平台捆绑功能。但这似乎是一个具有潜在挑战性副作用的大黑客。

最后,问题

是否有人通过JavaFX自包含应用程序部署获得了对JVM CLI参数的支持?如果是这样,您是如何完成它的?如果没有,还有其他建议吗?

2 个答案:

答案 0 :(得分:1)

您可以通过修改API写入的jvm用户覆盖配置文件来修改JVM的启动参数:

•Mac~ / Library / Application Support / [app.preferences.id] /packager/jvmuserargs.cfg •Windows C:\ Users [用户名] \ AppData \ Roaming [app.preferences.id] \ packager \ jvmuserargs.cfg •Linux~ / .local / [app.preferences.id] /packager/jvmuserargs.cfg

注意:这是一个内部实施细节,可能会有变化。

答案 1 :(得分:0)

我建议您通过复制和编辑平台java.c启动器来创建自己的本机启动器,而不是使用任何类型的两阶段启动系统,在那里您可以看到有什么选项,然后启动替换JVM。您可以在打开的JDK项目中看到他们正在做什么。

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/914cd9b482c8/src/share/bin/java.c

有很多地方他们正在寻找各种选项并将它们转换为JVM本身的init参数。看一下ParseArguments,AddApplicationOptions,TranslateApplicationArgs,CheckJvmType,AddOption等函数。

我不是C程序员,但我已经在很多场合维护了自己的启动程序:例如一个启动程序,它从一个每行一行的文本文件加载一个特定的类路径,可以检查到源代码控制和一个使用不同的入口点到main()。它没有那么大的变化,你可以很容易地隔离你的变化,这样它们很容易在更高版本的java.c上重新应用。出于您的目的,每次有人对java.c进行更改时,您都不需要进行更改,只有在JavaVMInitArgs或调用接口的其他一些关键方面发生更改时才需要更改它。

我确信,如果你提出并提供了一个更优雅的选项处理解决方案,也许在argv [0]不是' java'时表现不同,那么也许开放的jdk团队会采用你的接近并为您或我们所有人维护它。我相信有很多开发人员需要这些功能。