VSCODE:JAVAFX运行时组件缺少
我有一个Maven项目,我想导出到可运行的.jar文件中。
在VSCODE中,该项目无问题。导出的项目包括一个.jar文件和libs
带有所有javafx文件的文件夹:
Documents/prosjekt/target
├── classes
├── generated-sources
├── generated-test-sources
├── libs
│ ├── apiguardian-api-1.1.0.jar
│ ├── javafx-base-18.0.1-mac-aarch64.jar
│ ├── javafx-base-18.0.1.jar
│ ├── javafx-controls-18.0.1-mac-aarch64.jar
│ ├── javafx-controls-18.0.1.jar
│ ├── javafx-fxml-18.0.1-mac-aarch64.jar
│ ├── javafx-fxml-18.0.1.jar
│ ├── javafx-graphics-18.0.1-mac-aarch64.jar
│ ├── javafx-graphics-18.0.1.jar
│ ├── javafx-media-18.0.1-mac-aarch64.jar
│ ├── javafx-media-18.0.1.jar
│ ├── junit-jupiter-api-5.7.0.jar
│ ├── junit-jupiter-engine-5.7.0.jar
│ ├── junit-platform-commons-1.7.0.jar
│ ├── junit-platform-engine-1.7.0.jar
│ └── opentest4j-1.2.0.jar
├── maven-archiver
├── maven-status
├── surefire-reports
├── prosjekt_boilerplate-1.0-SNAPSHOT.jar
└── test-classes
当我运行以下命令时,问题发生:
❯ java -jar /Users/user/Documents/prosjekt/target/prosjekt_boilerplate-1.0-SNAPSHOT.jar
Error: JavaFX runtime components are missing, and are required to run this application
我不明白为什么会遇到此错误,因为所有Javafx文件位于libs
文件夹中。
我目前使用SDKMAN的Java Temurin 18.0.1。
❯ java -version
openjdk version "18.0.1" 2022-04-19
OpenJDK Runtime Environment Temurin-18.0.1+10 (build 18.0.1+10)
OpenJDK 64-Bit Server VM Temurin-18.0.1+10 (build 18.0.1+10, mixed mode)
pom.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>project</groupId>
<artifactId>prosjekt_boilerplate</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>prosjekt_boilerplate</name>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>18.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>18.0.1</version>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
asteroids.AsteroidsApp
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
编辑
我尝试下载javafx SDK并运行以下命令:
❯ java -jar --module-path /Users/user/Downloads/javafx-sdk-18.0.1/lib \
--add-modules=javafx.controls,javafx.media,javafx.fxml,javafx.graphics \
/Users/user/Documents/prosjekt/target/prosjekt_boilerplate-1.0-SNAPSHOT.jar
它可以使用!但这仍然没有回答我最初的问题。
I have a maven project that I want to export into a runnable .jar file.
In VSCode the project works without a problem. The exported project includes a .jar file and a libs
folder with all javaFX files:
Documents/prosjekt/target
├── classes
├── generated-sources
├── generated-test-sources
├── libs
│ ├── apiguardian-api-1.1.0.jar
│ ├── javafx-base-18.0.1-mac-aarch64.jar
│ ├── javafx-base-18.0.1.jar
│ ├── javafx-controls-18.0.1-mac-aarch64.jar
│ ├── javafx-controls-18.0.1.jar
│ ├── javafx-fxml-18.0.1-mac-aarch64.jar
│ ├── javafx-fxml-18.0.1.jar
│ ├── javafx-graphics-18.0.1-mac-aarch64.jar
│ ├── javafx-graphics-18.0.1.jar
│ ├── javafx-media-18.0.1-mac-aarch64.jar
│ ├── javafx-media-18.0.1.jar
│ ├── junit-jupiter-api-5.7.0.jar
│ ├── junit-jupiter-engine-5.7.0.jar
│ ├── junit-platform-commons-1.7.0.jar
│ ├── junit-platform-engine-1.7.0.jar
│ └── opentest4j-1.2.0.jar
├── maven-archiver
├── maven-status
├── surefire-reports
├── prosjekt_boilerplate-1.0-SNAPSHOT.jar
└── test-classes
The problem occurs when I run the following command:
❯ java -jar /Users/user/Documents/prosjekt/target/prosjekt_boilerplate-1.0-SNAPSHOT.jar
Error: JavaFX runtime components are missing, and are required to run this application
I don't understand why I get this error, since all the JavaFX files are located and visible in the libs
folder.
I currently use Java Temurin 18.0.1 from SDKman.
❯ java -version
openjdk version "18.0.1" 2022-04-19
OpenJDK Runtime Environment Temurin-18.0.1+10 (build 18.0.1+10)
OpenJDK 64-Bit Server VM Temurin-18.0.1+10 (build 18.0.1+10, mixed mode)
Pom.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>project</groupId>
<artifactId>prosjekt_boilerplate</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>prosjekt_boilerplate</name>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>18.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>18.0.1</version>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
asteroids.AsteroidsApp
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Edit
I tried downloading the JavaFX SDK and running the following command:
❯ java -jar --module-path /Users/user/Downloads/javafx-sdk-18.0.1/lib \
--add-modules=javafx.controls,javafx.media,javafx.fxml,javafx.graphics \
/Users/user/Documents/prosjekt/target/prosjekt_boilerplate-1.0-SNAPSHOT.jar
and it worked! But it still doesn't answer my original question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尽管这是解释性目的的一个很长的答案,但修复程序实际上非常简单。
另外唯一需要的是将带有模块的罐子放在模块路径上而不是类路径上。
回答您的问题以解释为什么您的原始方法失败。
您获得此错误的原因是您正在从类路径而不是模块路径上运行所有代码。
现代Javafx版本并未设计或支持从Class Path运行。它们应该从模块路径运行。
您已经完成了以下操作,这将使该程序仅在类Path上执行:
背景信息
您的应用程序类不需要模块化和其他能够从类路径执行而不是模块路径的(非Javafx)库,而不是模块路径,但是Javafx库将失败。
解决方案是至少将Javafx类放在模块路径上。理想情况下,您还可以使应用程序模块化(定义
module-info.java
文件),并仅使用非自动模块化罐(那些也定义amodule-info.java的jars
)在您的应用程序中。但是不需要理想(除非您要使用JLINK打包应用程序),否则仅在模块路径上使用Javafx类。您无法(当前)通过JAR清单将其他罐子或文件夹添加到模块路径上,就像当前使用ClassPath一样。有关此信息的信息,请参阅此问题的答案(以及有关此答案的评论):
相反,您需要指定在命令行中添加的模块的位置(或依赖于jlink创建的JRE image,该图像由JLINK创建所需的模块)。
此外,如果您的应用程序是模块化的,则应使用
-M
开关来指定由其所在的模块资格的主类,并且您的应用程序JAR也应在模块路径上。如果您的应用程序不是模块化的,则您仍然可以使用-jar
specifier,并在JAR清单中编码主类名称,而不是作为命令行开关。示例
,因此,假设您将应用程序分发为邮政编码,该邮政编码包含您的应用程序罐和依赖的库中的subforter库,则在名为lib的子文件夹中。
对于这些示例,应用程序罐是一个普通的薄罐(这不是一个胖罐,它已被阴影或包括Javafx运行时代码)。
对于非模块化应用程序,请在 Eden编码中进行讨论。用户解开包装的拉链后,假设主类名是在清单中编码的,则可以通过:
如果您使用其他不是传递依赖性的Javafx-Media(例如Javafx-Media)的应用程序,则还包括这些。
如果您的应用程序是模块化的,则您无需在JAR清单中编码额外的信息,但是您确实需要在JAR文件中包含
module-info.java
。在执行此操作时,最好将罐子与所使用的其余模块相同的LIB目录中,这样您也无需单独将其添加到模块路径中。执行此操作后,您可以这样运行该应用程序(此示例来自):您可以使用JAR命令设置主类来运行模块化JAR文件(也在Jenkov教程中演示)。 明确提供主类的情况下运行该模块化jar
然后,您可以在不 命令到JAR文件中,但我认为它不使用清单来执行此操作。目前,我不认为Maven Jar命令能够正确执行此操作(我认为它只是将信息放入清单中,而不是jar中的模块化主类执行信息)。
总而言之,使用Java模块和使用ClassPath是不同的且令人困惑的。 。 。 :-)
hack
(至少适用于Java 17)hack创建一个单独的启动器类,该类绕过运行时检查,以允许从模块路径而不是类Pather的Javafx框架启动但这不支持。我不推荐它,所以我不会在这里进一步解释。
进一步的建议,
由于命令行开关很容易误解或错误,因此在部署Javafx应用程序以提供特定于平台的执行脚本(UNIX/MAC Shell脚本或Windows batch文件)时,最好是用户可以更轻松地用于执行应用程序。
还要考虑使用Java运行时分发,无论是通过zipped Jlink映像还是JPackage创建的安装程序。这使您的用户更容易,因为这样他们就不需要找到并安装适当的Java运行时来使用您的应用程序。作为奖励,JLINK可以创建一个示例Shell脚本来执行您的应用程序。使用Maven-Javafx-Plugin的JLink选项并指定JlinkzipName,这很容易通过Maven进行。
jpackage可以创建用户可以单击运行应用程序的操作系统图标,但不能直接从maven-javafx-plugin中使用。
附加资源
更多信息,包括链接到包装选项的链接 javafx标签信息包装资源。
相关问题:使用Maven Assembly插件为Javafx项目创建一个多合一JAR?
Although this is a long answer for explanatory purposes, the fix is actually very simple.
The only thing additionally needed is to place the jars with the modules on the module path rather than the classpath.
Answering your question to explain why your original approach fails.
The reason you get this error is that you are running all code off of the classpath rather than the module path.
Modern JavaFX versions are not designed or supported to be run from the classpath. They should be run from the module path.
You have done the following things, which will make the program execute only on the classpath:
Background Info
Your application classes don't need to be modular and other (non-JavaFX) libraries that are able to be executed from the classpath rather than the module path will function when placed on the classpath, but the JavaFX libraries will fail.
The solution is to put, at a minimum, the JavaFX classes on the module path. Ideally, you might also make your application modular (define a
module-info.java
file for it) and use only non-automatic modular jars (those which also define amodule-info.java
) in your application. But the ideal is not required (unless you want to package your application using jlink), only having JavaFX classes on the module path is required.You cannot (currently) add other jars or folders to the module path via a jar manifest as you can currently do with the classpath. For information on this see the answer to this question (and the comments on this answer):
Instead, you need to specify the location of modules you add in the command line (or rely on a JRE image created by jlink that pre-bundles the required modules).
Additionally, if your application is modular you should use the
-m
switch to specify the main class qualified by the module it is in and your application jar should also be on the module path. If your application is not modular, then you can still use the-jar
specifier and encode the main class name in the jar manifest rather than as a command-line switch.Examples
So, let's say you have your application distributed as a zip that contains your app jar and dependent libraries in a sub-folder named lib.
For these examples, the application jar is a normal thin jar (it is not a fat jar which has been shaded or includes JavaFX runtime code).
For a non-modular application, this is discussed in eden coding. After the user has unzipped your package, and assuming the main class name is encoded in the manifest, then the application can be run via:
If you use additional JavaFX modules like javafx-media which are not transitive dependencies, then also include these.
If your application is modular, then you don't need to encode extra info in the jar manifest, but you do need to include a
module-info.java
in your jar file. When doing this it is probably best to put your jar in the same lib directory as the rest of the modules you are using so that you don't need to also add it separately to the module path. After doing this, you can run the application like this (this example is from the jenkov tutorial on Java modules):You can use a jar command to set a main class to run the modular jar file (also demonstrated in the jenkov tutorial). Then you can run that modular jar without providing the main class explicitly, but specifying the jar file and the module path (module path is still needed for JavaFX apps):
I don't know exactly what the jar command does to put add the execution commands into the jar file, but I don't think it uses the manifest to do this. At the moment, I don't think the maven jar command is capable of doing this correctly (I think it just puts info in the manifest and not modular main class execution info in the jar).
In summary using Java modules and using the classpath is different and confusing . . . :-)
Hack
There is (for Java 17 at least) a hack to create a separate launcher class that bypasses the runtime check to allow the startup of the JavaFX framework from the module path rather than the classpath, but it is not supported. I don't recommend it, so I won't explain it further here.
Further recommendations
Because the command line switches are easy to get wrong or mistype, it is best when deploying JavaFX applications to provide a platform-specific execution script (unix/mac shell script or windows batch file) that a user can more easily use to execute the application.
Also consider distributing with a Java runtime, either via a zipped jlink image or a jpackage created installer. That makes it easier on your users because then they don't need to find and install an appropriate java runtime to use your application. As a bonus, jlink can create an example shell script to execute your application. Doing this via maven is easy, using the jlink option of the maven-javafx-plugin and specifying the jlinkZipName.
jpackage can create an OS level icon the user can just click on to run the app, but can't be used directly from the maven-javafx-plugin.
Additional resources
Further info including links to packaging options like JPackageScriptFX in the javafx tag info packaging resources.
Related question: How can I create an all-in-one jar for a JavaFX project with the Maven Assembly plugin?