gpt4 book ai didi

java - JavaFX应用程序抛出NullPointerExceptions但仍然运行

转载 作者:行者123 更新时间:2023-12-02 09:05:35 24 4
gpt4 key购买 nike

我运行的每个JavaFX应用程序都抛出两个NullPointerExceptions。它们不会阻止甚至影响项目的执行,并且只有在以 Debug模式运行应用程序时才能看到它们。我什至在Oracle的HelloWorld示例和此最小程序中都遇到了这个问题:

public class JavaFXTSample extends Application {

@Override
public void start(Stage primaryStage) throws Exception {

StackPane iAmRoot = new StackPane();

Scene scene = new Scene(iAmRoot, 300, 250);

primaryStage.setScene(scene);
primaryStage.show();
}

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

这是第一个错误的堆栈跟踪:
 Thread [main] (Suspended (exception NullPointerException)) 
SystemProperties.setVersions() line: 81 [local variables unavailable]
SystemProperties.lambda$static$28() line: 67
30621981.run() line: not available
AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method]
SystemProperties.<clinit>() line: 64
LauncherImpl.startToolkit() line: 668
LauncherImpl.launchApplicationWithArgs(String, String, String[]) line: 337
LauncherImpl.launchApplication(String, String, String[]) line: 328
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: not available
LauncherHelper$FXHelper.main(String...) line: not available

这是第二个:
Thread [JavaFX Application Thread] (Suspended (exception NullPointerException)) 
PropertyHelper.lambda$getBooleanProperty$514(String) line: 39
7164036.run() line: not available
AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method]
PropertyHelper.getBooleanProperty(String) line: 37
Parent.<clinit>() line: 87
JavaFXTSample.start(Stage) line: 16
LauncherImpl.lambda$launchApplication1$162(AtomicBoolean, Application) line: 863
2266602.run() line: not available
PlatformImpl.lambda$runAndWait$175(Runnable, CountDownLatch) line: 326
32251660.run() line: not available
PlatformImpl.lambda$null$173(Runnable) line: 295
11305869.run() line: not available
AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]
PlatformImpl.lambda$runLater$174(Runnable, AccessControlContext) line: 294
30052382.run() line: not available
InvokeLaterDispatcher$Future.run() line: 95
WinApplication._runLoop(Runnable) line: not available [native method]
WinApplication.lambda$null$148(int, Runnable) line: 191
32126786.run() line: not available
Thread.run() line: not available

而且,如果我删除了 iAmRootscene的任何实例(因此 start()只是读取 primaryStage.show();),则不会发生第二个错误。为什么会这样呢?

我以前已经找到了这个问题( JavaFX application throws NullPointerException at startup),但是似乎没有人解决它,并且是两年多以前才问到的。

如果有帮助,我将在Windows 7 Professional上运行Eclipse 4.5.2,并且我根本不使用FXML。

编辑:

对于它的值(value),我找不到第二个错误的源代码,但是我发现了抛出第一个错误的方法的JavaFX代码(第81行):
58  private static final String versionResourceName =
59 "/com/sun/javafx/runtime/resources/version.properties";

...

78 private static void setVersions() {
79 int size;
80 InputStream is =
81 SystemProperties.class.getResourceAsStream(versionResourceName);
82 try {
83 size = is.available();
84
85 byte[] b = new byte[size];
86 int n = is.read(b);
87 String inStr = new String(b, "utf-8");
88 SystemProperties.setFXProperty("javafx.version",
89 getValue(inStr, "release="));
90
91 SystemProperties.setFXProperty("javafx.runtime.version",
92 getValue(inStr, "full="));
93
94 } catch (Exception ignore) {
95 }
96 }

最佳答案

免责声明

这个问题已经1岁了,但我觉得还是很相关的。这就是为什么我回答这个问题(长度)。

我将尽我所能回答这个问题

TL; DR

JavaFX有一些古怪的代码行,而异常是由这些代码行引起的。所有这些都可以追溯到JavaFX中的某些行,该行错过了检查或使用了未经检查的部分。

Every JavaFX application I've run throws two NullPointerExceptions. They don't prevent or even affect the execution of the projects, and I can only see them if I run my applications in debug mode.



第一个NullPointerException

您显示的第一个异常位于:

SystemProperties.setVersions() line: 81 [local variables unavailable]



您已经发布了相关代码。为了可视化,我将再次发布它。问题所在的行是:
InputStream is =
SystemProperties.class.getResourceAsStream(versionResourceName);
try {
size = is.available(); // InputStream "is" = null
...
} catch (Exception ignore) {
}

这很容易解释。 getResourceAsStream方法返回以下内容(来自 JavaDoc):

Returns: A InputStream object or null if no resource with this name is found



这意味着找不到资源(您已经再次发布) "/com/sun/javafx/runtime/resources/version.properties"

然而,这不是处理的 ,而是被忽略了。因此未打印此异常,但仍抛出该异常。它被调试器捕获,仅此而已。因此只能由调试器识别。

为什么并不能很好地识别其原因。一种可能是JDK不包含资源。在我对JDK-10的测试中(我目前正在使用),包com.sun.javafx.runtime存在,但子包资源不存在。由于com.sun软件包似乎没有记录,因此这实际上不是可重复的。 javafx的基本api记录在here中,但com.sun.javafx包中没有。如果您使用的是复杂的IDE(例如IntelliJ),则可以查看一下。我的JDK-8确实包含它。我在Ubuntu 18.04.1。上使用Oracle JDK。

一种可能是包装已沿途被抛弃。也许有人认为,通过包引用资源并不是那么好,并将其放在资源路径中,但是由于异常被吞没了,因此从未检测到此错误。

解决此问题

注意:此潜在修补程序尚未经过全面测试

如果您手动引入该资源,则可能会解决此问题。考虑到您发布的代码(可以在SystemProperties.setVersions方法中找到),您必须在com.sun.javafx.runtime.resources包中创建一个名为“version.properties”的文件。这个versions.properties应该看起来像这样:
release=1
full=1

这些是您必须测试的任意值。

第二个NullPointerException

第二个NullPointer Root 于PropertyHelper.lambda$getBooleanProperty$514(String) line: 39行中。该方法如下所示:
static boolean getBooleanProperty(final String propName) {
try {
boolean answer = AccessController.doPrivileged((java.security.PrivilegedAction<Boolean>) () -> {
String propVal = System.getProperty(propName);
return "true".equals(propVal.toLowerCase()); // Line 39
});
return answer;
} catch (Exception any) {
}
return false;
}

这导致结论,propVal为空,并由JavaDoc from System.getProperty支持

Returns: the string value of the system property, or null if there is no property with that key.



这意味着找不到propName。但是propName是方法参数。那么,propName是什么?再次可以在堆栈跟踪中找到。该行:

Parent.() line: 87



定义应找到的属性。它读取以下内容:
private static final boolean warnOnAutoMove = PropertyHelper.getBooleanProperty("javafx.sg.warn");

因此,前面所述的方法尝试找到SystemProperty“javafx.sg.warn”,但不检查它是否存在。再次没有处理,因此仅在调试器中可见。

如果将“toLowerCase”调用删除,则不会发生此异常。

解决此异常

您可以通过在
之前以任何方式引入以下代码 来简单地解决此异常:
System.setProperty("javafx.sg.warn", "true");

它必须在任何引用之前完成,因为此属性是静态的。因此,如果在代码中以任何方式引用了此类,则将加载它。一种可能是在您的主类中添加一个静态块,其中包含此代码。另一种方法是添加以下to the command line:

-Djavafx.sg.warn="true"



这将消除在引用之前调用代码的需要。当然,您可以将True换成其他任何东西。但是,有了该属性,问题行将不会抛出NullPointerException。

如果仅执行Stage.show,为什么不引发第二个异常?

这很简单。在JavaFx中,要显示的任何元素都是Scene graph中的Node。每个节点可能都有一个Parentwhich is a subclass of Node。几乎所有类都扩展了Parent,so does the StackPane,但扩展了not the Stage。通过引用StackPane,您引用了Parent,这触发了属性的加载。如果未设置StackPane,则不会引用Parent类,这意味着您不会触发该属性的加载。因此,不会抛出任何异常。

您应该修复异常(exception)吗?

由于javafx背后的团队似乎忽略了这些异常,因此您也可以这样做。我并不是说这是一种好习惯,也不应该以这种方式编写代码,但是要解决这些问题,这些问题不会阻止您运行此应用程序,并且不会更改行为,因此可能会花费更多的时间。

进一步的想法

这个答案解释了原始的“为什么”,但是我想为真正的问题付两美分。请注意,这只是我的意见!如果您确实有不同的想法,那完全可以。不再直接需要回答这个问题。

所有这些的根本原因(在我看来)是javafx api中许多代码的味道。从各个部分中的魔术字符串,到JavaFX组件中所有downcasting实现中的ParentHelper.ParentAccessor,经过许多大型类(甚至可能是神类),最后以不适当的亲密关系结束。抽象本来可以更好,并且(例如)Node类的大小可以达到巨大的目的。

对于new release cycle,我寄希望于他们花时间消除至少一些代码异味,但是我担心它们只是建立在这些代码异味的基础上,这意味着在某个时候,会有一个新的(“现代”)GUI -API必须被构建。

最后

祝你今天过得愉快!

关于java - JavaFX应用程序抛出NullPointerExceptions但仍然运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44684605/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com