NoSuchMethodError: <init>在com.sun.glass.ui.win.WinApplication.staticScreen_getScreens中。

10

自从升级到install4j 7.0.5和Java 10后,越来越多的在Windows上运行我们应用程序的用户报告应用程序抛出异常

java.lang.NoSuchMethodError: <init>
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.staticScreen_getScreens(Native Method)
    at javafx.graphics/com.sun.glass.ui.Screen.initScreens(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.Application.lambda$run$1(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)


UiLauncher (WAITING)
    at java.base@10.0.1/jdk.internal.misc.Unsafe.park(Native Method)
    at java.base@10.0.1/java.util.concurrent.locks.LockSupport.park(Unknown Source)
    at java.base@10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
    at java.base@10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
    at java.base@10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
    at java.base@10.0.1/java.util.concurrent.CountDownLatch.await(Unknown Source)
    at platform/javafx.graphics@10.0.1/com.sun.javafx.tk.quantum.QuantumToolkit.startup(Unknown Source)
    at platform/javafx.graphics@10.0.1/com.sun.javafx.application.PlatformImpl.startup(Unknown Source)
    at platform/javafx.graphics@10.0.1/com.sun.javafx.application.PlatformImpl.startup(Unknown Source)
    at platform/javafx.swing@10.0.1/javafx.embed.swing.JFXPanel.initFx(Unknown Source)
    at platform/javafx.swing@10.0.1/javafx.embed.swing.JFXPanel.<init>(Unknown Source)
    at java.base@10.0.1/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base@10.0.1/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at java.base@10.0.1/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.base@10.0.1/java.lang.reflect.Constructor.newInstance(Unknown Source)
    at java.base@10.0.1/java.lang.Class.newInstance(Unknown Source)
    at app//...

通过install4j创建的exe文件启动应用程序时,通过反射创建javafx.embed.swing.JFXPanel实例会触发错误:

Class.forName("javafx.embed.swing.JFXPanel").newInstance();
我们目前怀疑由于某种原因加载了不兼容的DLL(glass.dll似乎包含堆栈跟踪中提到的本地方法)。
有人知道如何防止出现此错误吗?例如,在通过install4j生成的exe执行应用程序时,是否有办法限制使用的java.library.path仅限于安装程序中嵌入并与应用程序一起本地安装的Java运行时环境? 根据一位用户的说法,如果使用“手动”启动应用程序,则不会出现该错误。
java -jar app.jar

看起来问题在于由install4j创建的可执行文件。


你能包含更多的堆栈跟踪吗? - Alan Bateman
1
@AlanBateman 已完成,但我强烈怀疑它不会有太大帮助。堆栈跟踪中的缩写行是调用 Class.newInstance 的应用程序代码。 - Thomas Behr
@nullpointer 安装程序中捆绑的 JRE 版本为 10.0.1。应用程序本身是一个兼容 Java 8 的遗留应用程序。 - Thomas Behr
1
@Holger install4j用于创建带有捆绑JRE的应用程序安装程序。该错误仅出现在某些用户(例如:在我们的测试机器上不会出现)身上,因此我认为捆绑的JRE并没有问题。相反,我怀疑另一个Java安装中的不兼容DLL以某种原因被加载。这就是为什么我问是否有人知道如何限制java.library.path(默认情况下,所有类型的系统路径,如C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;...都是java.library.path的一部分)。 - Thomas Behr
@ThomasBehr在这种情况下,我真的恳求您考虑以任何人都能轻松找到的方式创建有意义的日志。如果您将日志文件输出到易于查找的目录中,则用户上传它们将变得非常简单。考虑到此安装程序应用程序仅在主机上运行一次,我会默认使它们详细,并不太担心日志膨胀问题。在开发过程中,操作通常被遗忘,但它们是创建持久性、可维护软件的关键。 - flakes
显示剩余8条评论
1个回答

5
这个问题的解决方法似乎是从系统%PATH%中删除所有出现的"glass.dll"。我认为必须在其他地方实施修复,可能是在Java运行时或Install4j代码中,但不能在实际应用程序的Java代码中实施:由于某种原因,Install4j中的Java运行时版本在定位库时最后检查捆绑的JRE。在这种情况下,有问题的本机库是应该包含所请求的方法的"glass.dll",但如果在您的%PATH%中有旧的不兼容版本的"glass.dll"(例如来自以前的Java 8安装),则该文件将具有更高的优先级加载,然后应用程序将崩溃。这不是应用程序(Java代码)的问题,也不是捆绑的JDK的问题,而是install-4j生成的exe文件(或者可能是Java内部)尝试解析本机dll的问题。它应该首先检查捆绑的JRE目录,而不是先检查所有路径元素。
使用 Procmon,您可以看到它在路径中加载任意放置的 glass.dll 文件,首先:我将 JDK 1.8 中的一个文件添加到我的路径元素中,得到了以下结果(以及崩溃):

procmon log showing java loading the first glass.dll it can find


1
这似乎源于DLL搜索顺序。某些软件(可能是Java)使用包括PATH或当前工作目录在内的旧式顺序作为首选项。长期以来,推荐加载DLL的方式一直是使用SafeDllSearchModeLOAD_WITH_ALTERED_SEARCH_PATH。但这并不是Java与Windows接口中的唯一遗留部分... - Joey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接