如何创建自定义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方法。

通过代码跟踪实现:

  1. main.c for JVM在java.c中调用JLILaunch
  2. java.c 查找 Java类sun.launcher.LauncherHelper并使用JNI调用java类 ,调用checkAndLoadMain函数。
  3. 如果要启动的类没有main方法,但确实扩展了JavaFX应用程序类 ,则会创建一个包含启动参数的FXHelper类。
  4. 对FXHelper的引用通过JNI返回到java.c.
  5. java.c通过JNI 调用 FXHelper上的main方法 。
  6. FXHelper 使用reflection来调用com.sun.javafx.application.LauncherImpl.launchApplication() 。
  7. JavaFX LauncherImpl将设置应用程序类加载器,然后首先尝试在应用程序的主类上调用main()方法。
  8. 如果没有main()方法,JavaFX LauncherImpl将启动JavaFX启动程序线程 。
  9. 在启动程序线程上,LauncherImpl将在JavaFX应用程序上调用init() 。
  10. 在JavaFX应用程序线程上,LauncherImpl将创建一个新的Stage(窗口)并将其传递给应用程序的start方法 。
  11. 当最后一个阶段关闭或退出JavaFX平台时,LauncherImpl 将调用应用程序上的stop方法 。
  12. 所有调用跟踪都返回并且应用程序退出,因为没有其他任何操作可做。

如何自定义启动器

  1. 获取sun.launcher.LauncherHelper代码的副本。
  2. 忽略代码顶部的警告“这不是Sun Microsystems支持的任何API的一部分。如果您编写依赖于此的代码,则需要您自担风险。此代码及其内部接口可能会更改或删除,不另行通知。“ 并开始修改代码。
  3. 创建自己的FXHelper版本,它将调用您自己的LauncherImpl而不是JavaFX(在目标主应用程序类扩展您的应用程序框架类而不是JavaFX类的情况下)。
  4. 编写自己的LauncherImpl,为应用程序设置类加载器,创建应用程序类的实例,并在应用程序类型上调用所需的启动入口点。
  5. 运行您的应用程序,将sun.launcher.LauncherHelper和LauncherImpl的黑客版本放在引导类路径上 ,这样就可以获取它们而不是发布JDK的默认版本。

示例启动命令,假设要启动的目标应用程序是com.mycompany.MyApplication

 java -Xbootclasspath/p  com.mycompany.MyApplication