我已经将一个Swing应用程序迁移到了Java 8,最近我们看到了以下的NPE异常。
java.lang.NullPointerException
at java.awt.EventQueue.getCurrentEventImpl(EventQueue.java:848)
at java.awt.EventQueue.getCurrentEvent(EventQueue.java:842)
at java.awt.Component.requestFocusHelper(Component.java:7628)
at java.awt.Component.requestFocusHelper(Component.java:7620)
at java.awt.Component.requestFocus(Component.java:7495)
at javax.swing.JComponent.requestFocus(JComponent.java:1504)
at javax.swing.plaf.basic.BasicPopupMenuUI$MenuKeyboardHelper.stateChanged(BasicPopupMenuUI.java:1173)
at javax.swing.MenuSelectionManager.fireStateChanged(MenuSelectionManager.java:202)
at javax.swing.MenuSelectionManager.setSelectedPath(MenuSelectionManager.java:129)
at javax.swing.JPopupMenu.setVisible(JPopupMenu.java:784)
at javax.swing.JPopupMenu.show(JPopupMenu.java:965)
at org.tbee.swing.StandardComponentPopupMenu.showJTableMenu(StandardComponentPopupMenu.java:555)
at org.tbee.swing.StandardComponentPopupMenu$2.run(StandardComponentPopupMenu.java:175)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
由于使用了lambda表达式,因此迁回J7是个问题,所以我无法轻易确认这是否真的是一个J8问题。但是相关代码已经运行了几年时间,经历了Java 5、6和7的考验,因此很可能是J8特有的。
异常的原因是EventQueue中的currentEvent未设置。它应该通过setCurrentEventAndMostRecentTimeImpl(AWTEvent e)方法进行设置。然而,如果我在堆栈中向后跟踪,我发现在EventQueue:756(Java 1.8.0u45)之后,恰好调用了该方法并执行了派发操作。
if (event instanceof ActiveEvent) {
// This could become the sole method of dispatching in time.
setCurrentEventAndMostRecentTimeImpl(event);
((ActiveEvent)event).dispatch();
我不知道为什么那个变量是空的。由于所有事件都被代码片段处理,调试几乎是不可能的。
有人知道Swing在J8中的事件处理是否有变化吗?
EventQueue
实例吗? - HolgerEventQueue.getCurrentEvent()
并获得空返回,尽管在调用堆栈中我可以看到Component.dispatchEventImpl
(JEditorPane
)最近已经超过了应该将非空值设置为EventQueue.currentEvent
(由WeakReference
持有)的点。当调用堆栈中的代码仍然持有局部变量引用事件时,WeakReference被释放是有效的吗? - Luke UsherwoodinvokeLater
是一个好主意。(避免在处理其他事件时启动新的操作 - 您可能会遭受不一致/部分修改的内部状态。)不幸的是,我遇到的崩溃是不同的用例 - 代码需要立即回答“是否仍在处理同一事件?” - Luke Usherwood