Jpackage - 访问与包捆绑的资源

问题描述 投票:0回答:1

我使用 JPackageScriptFX 将 JavaFX 项目打包为安装程序,并且创建了一个名为“resources”的文件夹,该文件夹位于我的源包的 basedir 中。我已通过传递

--app-content resources
标志将此文件夹包含在我的包中:

$JAVA_HOME/bin/jpackage \
--type $INSTALLER_TYPE \
--dest target/installer \
--input target/libs \
--app-content resources \
--name "$NAME" \
--vendor "$VENDOR" \
--main-class ${MAIN_CLASS}.AppLauncher \
--main-jar ${MAIN_JAR} \
--java-options -Xmx2048m \
--runtime-image target/java-runtime \
--icon ${ICON} \
--app-version ${APP_VERSION} \

这是我的源代码文件夹目录结构:

Project
|
|-resources
|         |-icon.png
|
|-src
|
|-pom.xml
.
.
.

软件包创建并安装成功后,安装目录结构为:

Project
|
|-bin
|   |-project
|
|-lib
|   |-app
|   |   |-project.jar
|   |   |-project.cfg
|   |
|   |-resources
|   |         |-icon.png
|   |
|   |-runtime
|
|-share

当我运行该项目时,我得到了

FileNotFoundException
on 方法:
DBIO.loadResource

public class DBIO {
    private DBIO(){/*NOTHING*/}
    private static InputStream loadResource(String path){
        try{
            return new FileInputStream("resources/"+path);
        }catch(IOException ex){
            ex.printStackTrace();
        }
        return null;
    }
    public static final Image LOGO = new Image(loadResource("icon.png"));
}
java.io.FileNotFoundException: resources/icon.png (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(Unknown Source)
    at java.base/java.io.FileInputStream.<init>(Unknown Source)
    at java.base/java.io.FileInputStream.<init>(Unknown Source)
    at project.app.DBIO.loadResource(DBIO.java:24)
    at project.app.DBIO.<clinit>(DBIO.java:30)
    at project.app.EULAController.<clinit>(EULAController.java:29)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(Unknown Source)
    at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:941)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:983)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
    at project.app.App.start(App.java:16)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:263)
    at java.base/java.lang.Thread.run(Unknown Source)

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ExceptionInInitializerError
    at project.app.EULAController.<clinit>(EULAController.java:29)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(Unknown Source)
    at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(Unknown Source)
    at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:941)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:983)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
    at project.app.App.start(App.java:16)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:263)
    ... 1 more
Caused by: java.lang.NullPointerException: Cannot invoke "java.io.File.toPath()" because "file" is null
    at project.app.DBIO.writeToFile(DBIO.java:73)
    at project.app.Util.log(Util.java:43)
    at project.app.DBIO.loadResource(DBIO.java:26)
    at project.app.DBIO.<clinit>(DBIO.java:30)
    ... 27 more

编辑: 如果我将资源文件夹复制到

Project/bin
中,项目就会开始工作。这意味着程序正在 bin 内寻找资源文件夹。我应该如何将其指向正确的位置(在
/lib
内)?

javafx ioexception jpackage
1个回答
0
投票

前言:

通过覆盖 jpackage 使用的资源(例如属性和脚本的背景图像和模板文件),可以对生成的包进行高级自定义。

--resource-dir
选项用于为工具提供覆盖。

如果 jpackage 在打包应用程序时使用的默认资源不能满足您的需求,请创建一个目录并向其中添加您的自定义文件。如果覆盖文件,则自定义文件必须包含默认文件包含的所有属性。使用 --resource-dir 选项将目录路径传递给 jpackage。路径可以是绝对路径或相对于当前目录的路径。

https://docs.oracle.com/en/java/javase/21/jpackage/override-jpackage-resources.html

关于“--resource-dir”的解释:

覆盖 jpackage 资源的路径。 它可以是绝对路径或相对于当前目录的路径。

可以通过向此目录添加替换资源来覆盖 jpackage 的图标、模板文件和其他资源。

https://docs.oracle.com/en/java/javase/21/docs/specs/man/jpackage.html

附加信息:

如果您使用外部资源目录,那么您将面临这样的问题:您的 IDE 在开发过程中也必须使用该目录。您可能希望使用定制的“开关”在开发期间和项目打包时指向正确的资源目录。

或者您可以重写代码以在 JAR 中查找资源,如果那里不可用,请查看相对于您的 JAR 的指定目录。

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