使用 JavaFX 依赖项运行 jar 文件时出错

Error when running jar file using JavaFX dependencies

提问人:ZabbixJs 提问时间:11/3/2023 更新时间:11/3/2023 访问量:47

问:

我需要创建一个带有依赖项的 jar 文件,以便我可以在没有源代码文件的情况下传输它。但是当您通过双击启动这样的 jar 时,没有任何效果,但是如果您通过命令行以 java -jar 文件.jar 格式运行它,则会出现以下错误:

Exception in thread "main" java.lang.ExceptionInInitializerError
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.NullPointerException
        at uip.gui.JavaFxRun.<clinit>(JavaFxRun.java:16)
        ... 8 more

这是我的插件代码和启动代码:

<build>
 <plugins>
  <plugin>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-maven-plugin</artifactId>
   <executions>
     <execution>
      <goals>
       <goal>repackage</goal>
      </goals>
      <configuration>
    <classifier>spring-boot</classifier>
    <mainClass>
     uip.gui.JavaFxRun
    </mainClass>
      </configuration>
     </execution>
   </executions>
  </plugin>
 </plugins>
</build>

使用 JavaFX 的文件:

public class JavaFXClassFrame extends Application {

    static Logger LOGGER;

    static {
        try (FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(JavaFXClassFrame.class.getName());
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "Error ", e);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            URL xmlUrl = getClass().getResource("/fileFxml.fxml");
            loader.setLocation(xmlUrl);
            Parent root = loader.load();
            stage.setScene(new Scene(root));
            stage.show();
            LOGGER.log(Level.INFO, "Success ");
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "Error", e);
        }
    }
}
public class JavaFxRun {
    static Logger LOGGER;

    static {
        try (FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(JavaFxRun.class.getName());
        } catch (Exception e) {
            LOGGER.log(Level.WARNING, "Error ", e);
        }
    }

    public static void main(String[] args) {
        JavaFXClassFrame.main(args);
    }
}

JavaFX 启动文件:

public class JavaFxRun {
    static Logger LOGGER;

    static {
        try (FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(JavaFxRun.class.getName());
        } catch (Exception e) {
            LOGGER.log(Level.WARNING, "Error ", e);
        }
    }

    public static void main(String[] args) {
        JavaFXClassFrame.main(args);
    }
}
Java Maven JAR

评论


答:

2赞 Pino 11/3/2023 #1

正如堆栈跟踪所建议的那样,该问题是由 的第 16 行引起的,但该行中还有一个先前的问题:JavaFxRun

try (FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {

从文件系统读取文件,而不是从 JAR 读取文件;此外,如果解压缩 JAR,您会看到 的路径不是您指定的路径。FileInputStreamlog.config

尝试将该行替换为

try (InputStream ins = JavaFxRun.class.getResourceAsStream("/log.config")) {

此行使用表示类的对象的 getResourceAsStream() 方法。ClassJavaFxRun

评论

0赞 Stephen C 11/3/2023
是的。。。但这并不能解决整个问题。看看我的答案。
0赞 ZabbixJs 11/3/2023
我使用了你的提示,但它对:(没有帮助
1赞 Pino 11/3/2023
@ZabbixJs,“它没有帮助”并没有说明太多:你有不同的堆栈跟踪吗?这句话当然是错误的。您是否按照斯蒂芬的建议替换了电话?文件的名称是否正确?它的内容是什么?LOGGER.loglog.config
2赞 Stephen C 11/3/2023 #2

似乎您在此代码的某个地方未捕获NullPointerException

static Logger LOGGER;

static {
    try (FileInputStream ins = new FileInputStream("src/main/resources/log.config")) {
        LogManager.getLogManager().readConfiguration(ins);
        LOGGER = Logger.getLogger(JavaFxRun.class.getName());
    } catch (Exception e) {
        LOGGER.log(Level.WARNING, "Error ", e);
    }
}

要弄清楚这是在哪一行上发生的(即哪一行是 JavaFxRun.java 的第 16 行),但认为问题出在这条线上有点棘手:

     LOGGER.log(Level.WARNING, "Error ", e);

据我所知,这是唯一可以抛出 NPE 的线。事情是这样的:

  1. 您尝试打开“src/main/resources/log.config”。
  2. 这引发了一个原因是(可能)当应用程序在 IDE 外部运行时,该文件不在预期的文件系统位置。FileNotFoundException
  3. FNFE 被您的catch (Exception e) {...}
  4. 您尝试通过变量调用方法...和 NPE。LOGGER

NPE 的发生是因为没有初始化。发生这种情况是因为 FNFE 在执行 try 语句的正文之前就被抛出并捕获了。LOGGER

基本上,您不能使用日志记录系统来记录无法配置日志记录系统的情况。你能做的最好的事情就是将错误消息直接写入标准错误,并希望它能到达有用的地方。

注意:在这种情况下,替换为可以实际找到文件(或资源)的内容将修复触发 NPE 的 FNFE。但这还不是结束。如果(比如说)资源丢失了怎么办?找到的文件或资源是什么,但它包含乱码日志记录配置。您仍将获得 NPE!new FileInputStream("src/main/resources/log.config")

基本上,这种说法是错误的。它永远不会像你预期的那样工作。如果你到达那条线并尝试使用 ,NPE 是不可避免的。LOGGER.log(Level.WARNING, "Error ", e);LOGGER

评论

0赞 ZabbixJs 11/3/2023
那么我该如何修复错误呢?
0赞 ZabbixJs 11/3/2023
也就是说,我需要在代码或 maven 设置中更改什么才能使一切正常工作?
0赞 Stephen C 11/3/2023
我想我已经回答了这个问题。1) 将调用替换为代码,以将堆栈跟踪打印到 stderr。2) 读取堆栈跟踪以确认根本原因是缺少文件。3)修复丢失文件的问题;看看@Pino的回答。提示:如果要使用资源加载,请检查“log.config”文件是否已包含在 JAR 文件中的正确位置。如果找不到资源,该方法将返回...这也可能触发NPE。LOGGER.loggetResourceAsStream()null
2赞 Stephen C 11/3/2023
我应该指出,>您<有责任学习/理解 Java 语言,阅读/理解相应的 javadocs,并阅读/理解 Maven、Spring-boot 等的文档。依靠其他人来诊断您的问题并向您灌输有关如何解决这些问题的说明是无法扩展的。