关于swing AWT线程的`NullPointerException` - JLightweightFrame上的游标更新

时间:2016-08-30 12:33:32

标签: java swing javafx nullpointerexception

我的应用程序中有一个NullPointerException,只在一台特定的PC上发生,并且可以重现。我使用Javafx编写了我的GUI,并通过SwingNode在其上添加了一些Swing JPanel。

我该怎么办?

Exception-Time = 2016-08-30 06:55:50  UTC Exception-Tag = 0 Exception-Message = Thread AWT-EventQueue-0 (Id = 55) throw exception: null Stack-Trace = java.lang.NullPointerException
    at sun.swing.JLightweightFrame.updateClientCursor(Unknown Source)
    at sun.swing.JLightweightFrame.access$000(Unknown Source)
    at sun.swing.JLightweightFrame$1.updateCursor(Unknown Source)
    at sun.awt.windows.WLightweightFramePeer.updateCursorImmediately(Unknown Source)
    at java.awt.Component.updateCursorImmediately(Unknown Source)
    at java.awt.Container.validate(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

1 个答案:

答案 0 :(得分:1)

有关此问题的更多信息:

显然,这是JDK本身的一个错误(版本8和9),在JDK10之前可能不会修复。

sun.swing.JLightweightFrame.javaupdateClientCursor函数(第472-749行)抛出此异常:

private void updateClientCursor() {
    Point p = MouseInfo.getPointerInfo().getLocation();
    SwingUtilities.convertPointFromScreen(p, this);
    Component target = SwingUtilities.getDeepestComponentAt(this, p.x, p.y);
    if (target != null) {
        content.setCursor(target.getCursor());
    }
}

通常,这种情况正在发生,因为MouseInfo.getPointerInfo()可以返回NULL,例如,当您在图形设备之间移动时。 'MouseInfo'仍然可以保存以前的图形设备信息,如果鼠标已经移动到新的图形设备并且getPointerInfo()仍未更新为新的图形设备信息,则MouseInfo可以返回NULL。此方案将导致此行Null Pointer Exception上的MouseInfo.getPointerInfo().getLocation()尝试运行NULL对象的方法。

对我来说,当我在多屏幕机器上的显示器之间移动JavaFX应用程序窗口时,会抛出NPE。它不是每次都发生,但它很容易重现。 我在JavaFX SwingNode组件中使用Swing组件。

此错误在Oracle错误列表中已经是a known issue

代码修复: 此代码段显示了此错误的可选修复程序:

private void updateClientCursor() {
    PointerInfo pointerInfo = MouseInfo.getPointerInfo();
    if (pointerInfo == null) {
        /*
         * This can happen when JavaFX cannot decide
         * which graphics device contains the current
         * mouse position.
         */
        return;
    }
    Point p = pointerInfo.getLocation();
    SwingUtilities.convertPointFromScreen(p, this);
    Component target = SwingUtilities.getDeepestComponentAt(this, p.x, p.y);
    if (target != null) {
        content.setCursor(target.getCursor());
    }
}

Taken from JetBrains repository

可选解决方案:

由于这是一个正式的Oracle JDK的错误,我无能为力。在其他非正式JDK中应用了修复,例如OpenJDK,它应用了修复,但我不知道哪个版本将应用此修复。

对我来说,我可能会尝试编译并使用自己的JDK和应用的修复程序并在我的项目中使用它,但这是一个难以维护而且不那么灵活的解决方案。如果有人有其他修复/解决方法,我很乐意听到。