如何创建自定义JVM启动器?
有一个“ 如何在没有主要方法的情况下启动应用程序 ”的问题的历史,大多数陈述类似于“ 你不能 ”的东西。 我注意到现在只需通过扩展Application
即可启动JavaFX应用Application
。 我一直在使用类似于Application.launch()
的方法,但在这种情况下我总是将main方法视为样板代码。 所以我开始再次寻找答案。
我发现这个答案将我们与可以学习创建自己的JVM发射器的地方联系起来,但遗憾的是文章已不复存在。 我花了很长时间寻找任何可能暗示我应该做什么的事情,但没有结果。
我的问题
如何根据正在扩展的内容创建自定义JVM启动程序来启动应用程序? 例如,想象一个具有1个声明类的项目:
class MyApplcation extends App { }
启动项目不需要主要方法,因为它扩展了App。 这不是问题,尽管这是我的目标。 问题是有人如何创建自定义JVM启动器?
我的猜测是它会涉及使用某种基础,给我们某种骨架,但我不知道在哪里可以找到这样的东西。
JavaFX如何实现其应用程序执行模型
由于JEP 153的实现,可以启动不包含main方法的JavaFX应用程序:增强java命令行启动程序以启动JavaFX应用程序 。
这是对openjdk启动程序逻辑的修改,以检查要启动的类是否扩展了Application,如果是,则调用JavaFX特定的启动程序启动Java运行时和相关的线程,创建一个GUI窗口(在JavaFX术语中然后,Stage)创建了avaFX应用程序的实例,并根据JavaFX应用程序生命周期规则在应用程序上调用了init和start方法。
通过代码跟踪实现:
- main.c for JVM在java.c中调用JLILaunch
- java.c 查找 Java类sun.launcher.LauncherHelper并使用JNI调用java类 ,调用checkAndLoadMain函数。
- 如果要启动的类没有main方法,但确实扩展了JavaFX应用程序类 ,则会创建一个包含启动参数的FXHelper类。
- 对FXHelper的引用通过JNI返回到java.c.
- java.c通过JNI 调用 FXHelper上的main方法 。
- FXHelper 使用reflection来调用com.sun.javafx.application.LauncherImpl.launchApplication() 。
- JavaFX LauncherImpl将设置应用程序类加载器,然后首先尝试在应用程序的主类上调用main()方法。
- 如果没有main()方法,JavaFX LauncherImpl将启动JavaFX启动程序线程 。
- 在启动程序线程上,LauncherImpl将在JavaFX应用程序上调用init() 。
- 在JavaFX应用程序线程上,LauncherImpl将创建一个新的Stage(窗口)并将其传递给应用程序的start方法 。
- 当最后一个阶段关闭或退出JavaFX平台时,LauncherImpl 将调用应用程序上的stop方法 。
- 所有调用跟踪都返回并且应用程序退出,因为没有其他任何操作可做。
如何自定义启动器
- 获取sun.launcher.LauncherHelper代码的副本。
- 忽略代码顶部的警告“这不是Sun Microsystems支持的任何API的一部分。如果您编写依赖于此的代码,则需要您自担风险。此代码及其内部接口可能会更改或删除,不另行通知。“ 并开始修改代码。
- 创建自己的FXHelper版本,它将调用您自己的LauncherImpl而不是JavaFX(在目标主应用程序类扩展您的应用程序框架类而不是JavaFX类的情况下)。
- 编写自己的LauncherImpl,为应用程序设置类加载器,创建应用程序类的实例,并在应用程序类型上调用所需的启动入口点。
- 运行您的应用程序,将sun.launcher.LauncherHelper和LauncherImpl的黑客版本放在引导类路径上 ,这样就可以获取它们而不是发布JDK的默认版本。
示例启动命令,假设要启动的目标应用程序是com.mycompany.MyApplication
:
java -Xbootclasspath/p com.mycompany.MyApplication