英文:
Why isn't it enough put all JavaFX deps in the classpath w/o bothering about Java modules?
问题
我一直在尝试编写一个Hello JavaFX应用程序,并且面临着需要考虑Java模块以启动应用程序的必要性。
例如,javafx-maven-plugin的run目标会产生以下启动命令:
[DEBUG] 执行命令行:[C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe,
--module-path,C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar,
--add-modules,javafx.base,javafx.controls,javafx.graphics,
-classpath,D:\project\target\classes,org.pkg.pkg.App]
但是我的项目结构没有提到Java模块功能 - 我没有module-info.java文件。
我为什么不能将上述所有的JAR包放入应用程序的类路径中并感到满意呢?
例如:
C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=59556:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin"
-Dfile.encoding=UTF-8
-classpath D:\project\target\classes;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14-win.jar
org.pkg.pkg.App
如果我理解得正确并且根据包和模块规范
- 在类路径中定义的模块JAR被视为未命名模块
- 未命名模块会导出其所有包,即其中的所有内容都可见
但我遇到了错误
错误:缺少JavaFX运行时组件,需要这些组件来运行此应用程序
请问有人可以解释一下我在哪里出错了,关于Java模块如何工作?
提前谢谢!
英文:
I've been trying to write Hello JavaFX app and faced with necessity consider about Java modules for starting the app.
F.e. javafx-maven-plugin's run goal produce such startup command:
[DEBUG] Executing command line: [C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe,
--module-path, C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar,
--add-modules, javafx.base,javafx.controls,javafx.graphics,
-classpath, D:\project\target\classes, org.pkg.pkg.App]
But my project's structure doesn't mention Java module functionality - I didn't have module-info.java file.
Why can't I put all above JARs in the app classpath and be happy?
F.e.:
C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=59556:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin"
-Dfile.encoding=UTF-8
-classpath D:\project\target\classes;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-base\javafx-base-14-win.jar
org.pkg.pkg.App
If I'm right and understand Packages and Modules spec correctly
- module JARs defined in the classpath treated as unnamed modules
- unnamed modules export all their packages, i.e. everything is visible in them
But I get an error
Error: JavaFX runtime components are missing, and are required to run this application
Could someoune please explain me where I'm wrong here, about how Java modules work?
Thanks in advance!
答案1
得分: 2
警告: 尽管下面显示了您想要的是可能的,但将 JavaFX 模块放在类路径上是不受支持的。这意味着即使您自己的代码是非模块化的,您也应该将 JavaFX 放在模块路径上。
您_可以_将 JavaFX 放在类路径上,完全忽略模块<sup>1</sup>。然而,唯一的限制是您的主类不能再分配给 javafx.application.Application
<sup>2</sup>。解决方法是创建一个单独的主类,只需启动 JavaFX 应用程序。例如:
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
// 将 YourApp.class 替换为您的 Application 类
Application.launch(YourApp.class, args);
}
}
<sup>1. 您_实际上_不能完全忽略模块。类路径上的所有代码最终都会位于_未命名模块_中,运行时映像(即 JDK/JRE)中的所有模块仍然作为命名模块运行。</sup>
<sup>2. 这是由于实现细节。Java 包含的代码允许您在没有主方法的情况下启动 JavaFX 应用程序,只要主类可以分配给 Application
。但当它检测到主类可以分配给 Application
时,它会在引导 ModuleLayer
中检查 javafx.graphics
,这意味着它必须位于模块路径上,如果不在那里,那么它就会假设缺少 JavaFX。</sup>
英文:
Warning: Although the below shows what you want is possible, placing the JavaFX modules on the class-path is not supported. This means you should place JavaFX on the module-path, even when your own code is non-modular.
You can put JavaFX on the class-path and completely ignore modules<sup>1</sup>. However, the one caveat is that your main class can no longer be assignable to javafx.application.Application
<sup>2</sup>. The workaround is to create a separate main class that simply launches the JavaFX application. For example:
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
// where YourApp.class is replaced with your Application class
Application.launch(YourApp.class, args);
}
}
<sup>1. Your can't really ignore modules completely. All code on the class-path ends up in the unnamed module and all the modules in the run-time image (i.e. the JDK/JRE) still function as named modules.</sup>
<sup>2. This is due to an implementation detail. Java contains code which allows you to launch JavaFX applications without a main method, so long as the main class is assignable to Application
. But when it detects that the main class is assignable to Application
it checks for javafx.graphics
in the boot ModuleLayer
—meaning it must be on the module-path—and if not there then it assumes JavaFX is missing.</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论