在没有 Maven 或 IDE 的情况下从命令行运行 JavaFX 模块化应用程序时出现隐秘错误

问题描述 投票:0回答:1
我有一个 JavaFX Tetris 克隆,最初是使用 ide 和 Maven 进行依赖管理而制作的。一切都运行良好 - 然而,我想知道一切在幕后是如何工作的,所以我尝试在我的 ubuntu 终端中编译和运行该应用程序,而不使用 ide 或 maven。

我的项目结构中有所有 javafx 依赖项和 sqlite-jdbc 驱动程序/slj4 jar。

以下是我尝试编译和运行该应用程序所采取的步骤:

  1. cd 进入项目根目录 ~/Tetris,其中包含目录 lib、bin 和 src。 Lib 包含 javafx 模块,bin 用于 .class 文件输出和项目资源(图像文件、声音文件、最高分数数据库),src 包含源代码。

  2. 编译程序:

    javac --模块路径 lib --add-modules javafx.base,javafx.controls,javafx.graphics,javafx.media -d bin src/main/java/com/example/tetris/*.java

到目前为止一切正常。

  1. 运行程序:

    java --module-path lib --add-modules javafx.base,javafx.controls,javafx.graphics,javafx.media -cp bin:lib / sqlite-jdbc-3.45.3.0.jar:lib / sl4j-api- 1.7.36.jar src/main/java/com/example/tetris/Main.java

在此命令中,我将 sqlite 驱动程序和 sl4j 添加到类路径并尝试运行该程序。首先,我得到控制台输出,表明程序正在运行: 表“top_players”创建成功。 表中的行数:3 N:AAA,S:10000 N:BBB,S:5000

但不久之后,它崩溃了,我收到了这个神秘的错误:

Exception in Application start method Exception in thread "main" java.lang.IllegalArgumentException: 0 > -4 at java.base/java.util.Arrays.copyOfRange(Arrays.java:3782) at java.base/java.util.Arrays.copyOfRange(Arrays.java:3742) at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:431) at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192) at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
这就是它给我的全部信息,没有其他信息。有谁知道我可能遗漏了什么或做错了什么?

如果有帮助的话,我使用的是 Ubuntu 系统。我已将 jdk 和 javafx 添加到我的 PATH 中。我真的很难过。感谢任何看到并回复的人。

java linux javafx
1个回答
0
投票
该错误(我认为)是

JEP 330:启动单文件源代码程序实现中的错误1。可以使用以下内容进行复制:

import javafx.application.Application; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage primaryStage) { throw new RuntimeException("test"); } public static void main(String[] args) { launch(Main.class, args); } }
命令行:

java -p <path-to-javafx> --add-modules javafx.graphics Main.java
输出:

Exception in Application start method Exception in thread "main" java.lang.IllegalArgumentException: 0 > -2 at java.base/java.util.Arrays.copyOfRange(Arrays.java:3807) at java.base/java.util.Arrays.copyOfRange(Arrays.java:3767) at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.execute(SourceLauncher.java:273) at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:153) at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:78)
无论出于何种原因,如果单文件源是 JavaFX 应用程序并且对 

launch

 的调用抛出异常,那么您会得到那个奇怪的 
IllegalArgumentException
。然而,如果您直接从 
main
 抛出异常,那么您会像平常一样看到该异常。也许实施
launch
所涉及的反思会搞乱事情。

无论如何,您首先要编译程序,因此您一开始就不应该使用 JEP 330 功能。这意味着您应该将

类名传递给java

,而不是
源文件。根据您在问题中提供的信息,您的命令应该是:

java -p lib --add-modules javafx.controls,javafx.media -cp bin:lib/sqlite-jdbc-3.45.3.0.jar:lib/sl4j-api-1.7.36.jar com.example.tetris.Main
注意几点:

  1. 最后一位是主类的完全限定名称(而不是源文件的路径)。该类将位于类路径上。

  2. -p

    --module-path
     的缩写形式。

  3. javafx.controls

    javafx.media
     
    need 包含在 --add-modules
     中,因为其他所需的 JavaFX 模块将被这两个需要它们的模块隐式拉入。虽然显式添加每个单独的 JavaFX 模块并没有错,只是没有必要。

也就是说,您的应用程序仍然有可能抛出异常。但现在您应该能够看到真正的异常,而不是那个神秘的

IllegalArgumentException


1。我为此提交了一次错误,但被拒绝为“不可重现”。该评论解释了他们如何尝试重现它,但他们未能使用 JEP 330。我的后续行动没有收到任何回复。所以,据我所知,OpenJDK 开发人员仍然没有意识到这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.