简体   繁体   中英

`NullPointerException` on swing AWT thread - cursor update on JLightweightFrame

I have a NullPointerException in my application, that happens only on one specific PC, and is reproducible. I wrote my GUI using Javafx with some Swing JPanels on it via SwingNode.

What should I do?

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)

More about the problem:

Apparently, this is a bug at the JDK itself (versions 8 and 9) and probably won't get fixed until JDK10.

This exception is thrown from within the sun.swing.JLightweightFrame.java class, at the updateClientCursor function (lines 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());
    }
}

In general, this is happening because MouseInfo.getPointerInfo() can return NULL, for example, when you move between graphic devices. 'MouseInfo' can still hold the former graphic device information, then getPointerInfo() can return NULL if the mouse already moved to the new graphic device and MouseInfo still didn't updated to the new graphic device information. this scenario will cause a Null Pointer Exception on this line MouseInfo.getPointerInfo().getLocation() for trying to run a method of a NULL object.

For me, NPE is thrown when I move my JavaFX app window between monitors on my multiscreen machine. Its not happening every time but it is reproducible very easily. I'm using a Swing component in a JavaFX SwingNode component.

This bug is already a known issue at Oracle bug list.

Code Fix: This snippet shows an optional fix for this bug:

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

Optional solution:

Since it is a bug withing the formal Oracle JDK, there is no much I can do about it. there are fixes applied in other non-formal JDKs like OpenJDK for example, which applied a fix, but I don't know which version will apply this fix yet.

For me, I would probably try to compile and use my own JDK with the applied fix and use it in my project, but this is a hard to maintain and not so flexible solution. If someone have another fix/workaround I would be happy to hear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM