当前位置: 首页 > 知识库问答 >
问题:

了解主类如何影响JPM

欧金鹏
2023-03-14

我有一个非常基本的JavaFX应用程序,如果应用程序类不是主类,它可以完美无缺地工作:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;

public class Main {

    public static void main(String[] args) {
        Application.launch(App.class, args);
    }

}

public class App extends Application {

    @Override
    public void start(Stage primaryStage) {
        FXMLLoader loader = new FXMLLoader(); // works
    }

}

但是,当我将两者合并在一起时(这是大多数html" target="_blank">教程,包括OpenJFX的官方文档中推荐的方式),模块系统会抛出illegalAccessErr(至少在OpenJDK 11.0.2上):

public class MainApp extends Application {

    @Override
    public void start(Stage primaryStage) {
        FXMLLoader loader = new FXMLLoader(); // throws IllegalAccessError
    }

    public static void main(String[] args) {
        launch(MainApp.class, args);
    }

}

例外情况是:

java.lang.IllegalAccessError:类com.sun.javafx.fxml.fxmlLoaderHelper(在未命名的模块@0x642C1A1B中)无法访问类com.sun.javafx.util.utils(在模块javafx.graphics中),因为模块javafx.graphics不会将com.sun.javafx.util导出到未命名的模块

奇怪的是,我没有积极地使用模块系统。我没有在我的项目中添加module-info.java。所以我假设所有的东西都应该导出到任何未命名的模块?但这根本不是重点。

主要的问题是:为什么相同的代码如果分布在两个类中会有不同的行为?在这两种情况下,fxmlloader都使用com.sun.javafx.fxml.fxmlloaderhelper,后者又使用com.sun.javafx.util.utils。所以我要么在两种情况下都得到异常,要么在无情况下得到异常。有什么区别呢?

共有1个答案

卫劲
2023-03-14

有一些答案已经张贴,可以部分适用于您的问题,但它可能是方便的收集他们在这里,并提出他们在一个完整的答案。

应用程序类

在对Maven Shade JavaFX运行时组件缺失的回答中,我解释了当您使用application类作为主类时,希望您使用模块系统的原因。

这个错误来自java.base模块(链接)中的sun.launcher.launcherHelper

如果主应用程序扩展了application并具有main方法,LauncherHelper将检查javafx.graphics模块是否作为命名模块出现:

Optional<Module> om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
if (!om.isPresent()) {
    abort(null, "java.launcher.cls.error5");
}

如果该模块不存在,则中止发射。

但是,如果不通过application类运行,则不会进行该检查。

主类

对于Maven和Eclipse之间启动JavaFX11应用程序的不同行为的另一个答案解释了当您使用Launcher类(一个不扩展应用程序的主类)和Mavenexec:java插件时,它在没有模块化系统的情况下工作的原因。

    null

如果在运行main.main()时检查命令行:

/path/to/jdk-11.0.2.jdk/Contents/Home/bin/java \
    "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=60556:/Applications/IntelliJ IDEA.app/Contents/bin"  \
    -Dfile.encoding=UTF-8  \
    -classpath /path/to/so-question-54756176-master/target/classes:/path/to/.m2/repository/org/openjfx/javafx-base/11.0.2/javafx-base-11.0.2.jar:.../path/to/.m2/repository/org/openjfx/javafx-fxml/11.0.2/javafx-fxml-11.0.2-mac.jar  \
    Main

JavaFX SDK中的所有JavaFX JAR都被添加到类路径中,您正在运行经典的java-cp...main

缺少javafx.fxml

Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x5fce9dc5) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x5fce9dc5
    at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
    at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)

您的错误显示您正在使用FXML,但它无法在module-path中解析,因此它试图通过反射访问,但由于您没有将javafx.graphics打开到未命名的模块,因此失败。

所以现在您会问:我一开始就没有设置javafx.graphics

好吧,你没有,但IntelliJ为你做的!

/path/to/jdk-11.0.2.jdk/Contents/Home/bin/java \
    --add-modules javafx.base,javafx.graphics \
    --add-reads javafx.base=ALL-UNNAMED \
    --add-reads javafx.graphics=ALL-UNNAMED \
    "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=60430:/Applications/IntelliJ IDEA.app/Contents/bin" \
    -Dfile.encoding=UTF-8 \
    -classpath /path/to/so-question-54756176-master/target/classes:/path/to/.m2/repository/org/openjfx/javafx-base/11.0.2/javafx-base-11.0.2.jar:.../.m2/repository/org/openjfx/javafx-graphics/11.0.2/javafx-graphics-11.0.2-mac.jar \
    MainApp

您可以看到IntelliJ默认添加javafx.basejavafx.graphics。因此只缺少javafx.fxml(然后当然应该添加module-path)。

正如您所指出的,推荐的解决方案在文档中:

或者在命令行上,使用--module-path包含JavaFX SDK库文件夹的路径,在这种情况下使用--add-module包含JavaFX.fxml(您没有控件)。

或者使用Maven插件。在某个时候,您将不得不离开IDE,因此您将需要使用插件来运行应用程序。

Maven exec

关于Mavenexec插件的最后一点注意事项,以备您使用:

此外,在模块化系统的插件exec:java被修复之前,推荐的Maven解决方案将使用exec:exec,如本期所述,因此您可以指定两个vm参数。

 类似资料:
  • 问题内容: 说,我有以下mixin通过触摸彼此重叠: 如果我希望我的视图通过该命令,请检查A->检查B,我的代码应该是还是? 为什么我们总是将其子类或子类放在mixins之后?(我通过阅读django通用视图的源代码注意到了这一点,但我不知道其背后的原理,如果有的话) 问题答案: MRO基本上是深度优先,从左到右。有关更多信息,请参见新型Python类中的方法解析顺序(MRO)。 你可以查看要检查

  • 我知道线程是并发运行的,所以您无法预测执行的顺序,但在提供的代码中,我在运行其他代码之前加入了thread。如果应该等到线程执行完毕,那么为什么顺序仍然是随机的呢?在两个print语句之前加入任何内容总是会导致它们最后被打印,而如果我在之后加入所有内容,它并不总是最后,为什么?

  • 问题内容: 是否可以定义默认情况下在哪个架构中创建新表?(由“不合格的表名”引用。) 我已经在Postgres中看到了有关使用“搜索路径”的一些详细信息,但是我认为它仅在检索数据而不是创建时才起作用。 我有一堆SQL脚本,它们创建许多表。我不想修改脚本,而是希望在默认模式下将数据库创建表设置为特定的模式-当它们具有非限定名称时。 这可能吗? 问题答案: 搜索路径的确是您想要的:

  • 我想知道为什么“k”和“a”的结果不同。唯一的区别是,我在创建k时添加了一对额外的括号。我认为结果应该是一样的。我的环境是Eclipse EE 2021,JDK17。如果您能分享您的观点,我们将不胜感激。 结果:

  • 问题内容: 以下两个查询有什么区别? 问题答案: 在SQL方面,绝对没有区别:这两个查询完全相同。 (您可以通过回显它们进行检查) 是的更完整的语法,允许使用: 有关更多信息,您应该阅读手册的 变量解析/复杂(curly)语法 部分 (引用几句话) : 之所以称其为“复杂”,是因为语法复杂,而是因为它允许使用复杂的表达式。 可以通过此语法包括具有字符串表示形式的任何标量变量,数组元素或对象属性。

  • 本文向大家介绍物联网如何影响大数据,包括了物联网如何影响大数据的使用技巧和注意事项,需要的朋友参考一下 当涉及到当今最受关注的两种技术时,大数据和物联网(IoT)可能正处于主导地位。在过去的几年中,大数据在许多领域都取得了进步。尽管物联网恰好与众不同,但它已与大数据紧密相连。 什么是大数据? 大数据本质上是大量复杂形式的数据。具体来说,它还涉及使用预测分析和方法,这些方法和方法可从此类数据中提取有