如何将带有额外模块的 JavaFX 导出到 JAR
How do I export a JavaFX with extra modules to a JAR
我目前有一个应用程序使用了一些导入的模块,例如 Jackson 和 MSSQL JDBC。我目前不使用 Maven、Gradle 或 ANT 等任何工具。
我尝试导出 JavaFX JAR,并将它们提取到 JAR 中,如下图所示。
但是我得到了错误:
Error: Could not find or load main class apicall.Main
Caused by: java.lang.ClassNotFoundException: apicall.Main
当我包含它们而不提取它们时,如下图所示:
然后应用程序 运行s 但是当我尝试调用 SQL 数据库时抛出以下错误:java.sql.SQLException: No suitable driver found for jdbc:sqlserver
我目前通过在控制台中键入以下命令来 运行 JAR:
java --module-path "C:\Program Files\Java\javafx-sdk-15\lib" --add-modules javafx.controls,javafx.fxml -jar APICall.jar
如何使用上面列出的相同或类似命令将 JavaFX JAR 和我需要的所有模块导出到 运行?
编辑:JAR结构如下:
堆栈跟踪如下所示:
答案取决于一件事:
is APICall a modular jar? does it contains a module-info.java?
如果APICall是一个模块化jar,它只能访问模块导出的包而不能访问class路径。
如果 APICall 不是模块化 jar,那么它必须成为一个“自动模块”才能访问模块和 classpath 导出的包。
来自提供的依赖项列表:
- javafx 依赖项是模块
- jackson 依赖是模块
- commons-io 不是模块
- mysql-jdbc不是模块
那么我们来说说第一个选项
API调用是一个模块
这意味着,jar 包含一个 module-info 并且明确需要他执行所需的包。这也意味着 APICall 无法访问 commons-io 和 mysql-jdbc 如果它们在 class 路径中。因此必须将 commons-io 和 mysql-jdbc 添加到要转换为自动模块并可访问的模块路径。必须将适当的“require”子句添加到模块信息文件中。
对于 运行 应用程序,您需要提供 3 样东西:
- 使用--module-path 或-p
在哪里可以找到依赖模块和主模块
- 哪个模块是主模块使用--module或-m
- 主要class到运行(如果MANIFEST文件没有提供)
命令类似于:
java --module-path <list of folders containing javafx/jacksons/commons/mysqljdbc/APICall jars> --module <APICall module name>/apicall.Main
API调用不是模块
这意味着,jar 不包含模块信息,并且必须在命令行中显式提供所需的模块依赖项。这也意味着 APICall 必须成为一个自动模块来访问模块和 classpath.
对于运行申请,您需要提供 4 样东西:
- 使用 --module-path 或 -p
在何处查找依赖模块
- 在哪里可以使用 --class-path 或 -classpath 或 -cp
找到相关的非模块化 jar
- 哪个模块是主模块使用--module或-m
- 主要class到运行(如果MANIFEST文件没有提供)
知道自动模块名称如果未在 MANIFEST 文件中提供是从版本中剥离的 jar 名称,那么 APICall.jar 自动模块名称将是“APICall”
命令类似于:
java --module-path <list of folders containing javafx/jacksons/APICall jars> --add-modules <list of module names required by APICall> --class-path <path to commons-io/mysql-jdbc jars> --module APICall/apicall.Main
PS:如果你不想提供要加载的模块列表到 --add-modules 参数,你可以使用这个常量“ALL-MODULE-PATH”,它将加载所有在模块路径
中找到的模块
英语不是我的语言所以我希望我足够清楚
编辑:
关于你的APICall.jar:
无法按原样加载内部结构。 Jar 不能包含 jar。
它可以通过使用自定义 classloader 来实现,但这将是一个棘手的问题。 springboot就用了这种classloader,想看的话
无论如何,我猜您正在尝试创建一个“胖”罐子。手动创建一个 fat jar 是个坏主意。可以犯这么多错误。所以我建议你使用一些构建工具,比如 gradle 或 maven 来创建它。
这些是关于您的 jar 内容的一些评论:
- apicall: 你的app的基础包,这个就可以了
- com:又是一个基础包,可能是提取javafx或者jackson依赖的结果。好的
- javafx:基础包,javafx的jar解压后的结果。您已经使用 --module-path 提供了这些模块,那么为什么将它们包含在您的 jar 中?
- javafx.base:从javafx.base.jar 中提取的模块。 KO。 jar 不能包含模块,只能包含包。 “javafx.base”不是有效的程序包名称。这不会被加载
- javafx.controls:同上
- javafx.fxml:同上
- javafx.graphics:同上
- javafx.media:同上
- javafx.swing:同上
- javafx.web:同上
- META-INF:包含一个 MANIFEST 文件,其中可能包含您应用的主要 class。最重要的一点是“服务”文件夹。它必须包含与它们提供的服务接口同名的文件,其中包含实现 classes 的列表。 Jackson 和 mssql jar 提供这些服务。你 add/merge 那些文件了吗?
- microsoft:如果您正在创建一个 fat jar,则缺少这个。这个包存在于 mssql-driver jar 但不在你的 jar
- mssql:如果你正在创建一个 fat jar,这个就丢失了。这个包存在于 mssql-driver jar 但不在你的 jar
- org:如果你正在创建一个胖罐子,这个就不见了。这个包存在于 commons-io jar 但不在你的 jar
- commons-io-2.8.0.jar:无法访问,必须提取
- jackson-annotations-2.11.3.jar:无法访问,必须提取
- jackson-core-2.11.3.jar:无法访问,必须提取
- jackson-databind-2.11.3.jar:无法访问,必须提取
- 模块-info.class:里面是什么?
- mssql-jdbc-8.4.1.jre14.jar:无法访问,必须提取
总而言之:你的罐子一团糟。
我建议你:
- 不要创建 fat jar 并使用本文顶部提供的解决方案 post
- 使用 fat jar 但使用 gradle 或 maven
编辑:
并添加到列表中 错误的
根据您的评论,您缺少文件
/META-INF/services/java.sql.Driver
需要此文件来为 java.sql API
注册驱动程序
您可以在 mssql-jdbc-8.4.1.jre14.jar 中找到一个,其中包含行
com.microsoft.sqlserver.jdbc.SQLServerDriver
没有它,你将永远得到:
java.sql.SQLException: No suitable driver found for jdbc:sqlserver
我目前有一个应用程序使用了一些导入的模块,例如 Jackson 和 MSSQL JDBC。我目前不使用 Maven、Gradle 或 ANT 等任何工具。
我尝试导出 JavaFX JAR,并将它们提取到 JAR 中,如下图所示。
但是我得到了错误:
Error: Could not find or load main class apicall.Main
Caused by: java.lang.ClassNotFoundException: apicall.Main
当我包含它们而不提取它们时,如下图所示:
然后应用程序 运行s 但是当我尝试调用 SQL 数据库时抛出以下错误:java.sql.SQLException: No suitable driver found for jdbc:sqlserver
我目前通过在控制台中键入以下命令来 运行 JAR:
java --module-path "C:\Program Files\Java\javafx-sdk-15\lib" --add-modules javafx.controls,javafx.fxml -jar APICall.jar
如何使用上面列出的相同或类似命令将 JavaFX JAR 和我需要的所有模块导出到 运行?
编辑:JAR结构如下:
堆栈跟踪如下所示:
答案取决于一件事:
is APICall a modular jar? does it contains a module-info.java?
如果APICall是一个模块化jar,它只能访问模块导出的包而不能访问class路径。
如果 APICall 不是模块化 jar,那么它必须成为一个“自动模块”才能访问模块和 classpath 导出的包。
来自提供的依赖项列表:
- javafx 依赖项是模块
- jackson 依赖是模块
- commons-io 不是模块
- mysql-jdbc不是模块
那么我们来说说第一个选项
API调用是一个模块
这意味着,jar 包含一个 module-info 并且明确需要他执行所需的包。这也意味着 APICall 无法访问 commons-io 和 mysql-jdbc 如果它们在 class 路径中。因此必须将 commons-io 和 mysql-jdbc 添加到要转换为自动模块并可访问的模块路径。必须将适当的“require”子句添加到模块信息文件中。
对于 运行 应用程序,您需要提供 3 样东西:
- 使用--module-path 或-p 在哪里可以找到依赖模块和主模块
- 哪个模块是主模块使用--module或-m
- 主要class到运行(如果MANIFEST文件没有提供)
命令类似于:
java --module-path <list of folders containing javafx/jacksons/commons/mysqljdbc/APICall jars> --module <APICall module name>/apicall.Main
API调用不是模块
这意味着,jar 不包含模块信息,并且必须在命令行中显式提供所需的模块依赖项。这也意味着 APICall 必须成为一个自动模块来访问模块和 classpath.
对于运行申请,您需要提供 4 样东西:
- 使用 --module-path 或 -p 在何处查找依赖模块
- 在哪里可以使用 --class-path 或 -classpath 或 -cp 找到相关的非模块化 jar
- 哪个模块是主模块使用--module或-m
- 主要class到运行(如果MANIFEST文件没有提供)
知道自动模块名称如果未在 MANIFEST 文件中提供是从版本中剥离的 jar 名称,那么 APICall.jar 自动模块名称将是“APICall”
命令类似于:
java --module-path <list of folders containing javafx/jacksons/APICall jars> --add-modules <list of module names required by APICall> --class-path <path to commons-io/mysql-jdbc jars> --module APICall/apicall.Main
PS:如果你不想提供要加载的模块列表到 --add-modules 参数,你可以使用这个常量“ALL-MODULE-PATH”,它将加载所有在模块路径
中找到的模块英语不是我的语言所以我希望我足够清楚
编辑:
关于你的APICall.jar:
无法按原样加载内部结构。 Jar 不能包含 jar。 它可以通过使用自定义 classloader 来实现,但这将是一个棘手的问题。 springboot就用了这种classloader,想看的话
无论如何,我猜您正在尝试创建一个“胖”罐子。手动创建一个 fat jar 是个坏主意。可以犯这么多错误。所以我建议你使用一些构建工具,比如 gradle 或 maven 来创建它。
这些是关于您的 jar 内容的一些评论:
- apicall: 你的app的基础包,这个就可以了
- com:又是一个基础包,可能是提取javafx或者jackson依赖的结果。好的
- javafx:基础包,javafx的jar解压后的结果。您已经使用 --module-path 提供了这些模块,那么为什么将它们包含在您的 jar 中?
- javafx.base:从javafx.base.jar 中提取的模块。 KO。 jar 不能包含模块,只能包含包。 “javafx.base”不是有效的程序包名称。这不会被加载
- javafx.controls:同上
- javafx.fxml:同上
- javafx.graphics:同上
- javafx.media:同上
- javafx.swing:同上
- javafx.web:同上
- META-INF:包含一个 MANIFEST 文件,其中可能包含您应用的主要 class。最重要的一点是“服务”文件夹。它必须包含与它们提供的服务接口同名的文件,其中包含实现 classes 的列表。 Jackson 和 mssql jar 提供这些服务。你 add/merge 那些文件了吗?
- microsoft:如果您正在创建一个 fat jar,则缺少这个。这个包存在于 mssql-driver jar 但不在你的 jar
- mssql:如果你正在创建一个 fat jar,这个就丢失了。这个包存在于 mssql-driver jar 但不在你的 jar
- org:如果你正在创建一个胖罐子,这个就不见了。这个包存在于 commons-io jar 但不在你的 jar
- commons-io-2.8.0.jar:无法访问,必须提取
- jackson-annotations-2.11.3.jar:无法访问,必须提取
- jackson-core-2.11.3.jar:无法访问,必须提取
- jackson-databind-2.11.3.jar:无法访问,必须提取
- 模块-info.class:里面是什么?
- mssql-jdbc-8.4.1.jre14.jar:无法访问,必须提取
总而言之:你的罐子一团糟。
我建议你:
- 不要创建 fat jar 并使用本文顶部提供的解决方案 post
- 使用 fat jar 但使用 gradle 或 maven
编辑:
并添加到列表中 错误的
根据您的评论,您缺少文件
/META-INF/services/java.sql.Driver
需要此文件来为 java.sql API
注册驱动程序您可以在 mssql-jdbc-8.4.1.jre14.jar 中找到一个,其中包含行
com.microsoft.sqlserver.jdbc.SQLServerDriver
没有它,你将永远得到:
java.sql.SQLException: No suitable driver found for jdbc:sqlserver