NPE 在 NodeList 上调用 getLength()
Posted
技术标签:
【中文标题】NPE 在 NodeList 上调用 getLength()【英文标题】:NPE calling getLength() on NodeList 【发布时间】:2015-07-22 08:39:38 【问题描述】:我正在使用 org.w3c.dom.Document 接口来解析在客户端和服务器之间传递的 XML 消息。我时不时地遇到一个我无法解释的 NPE。
事件链如下:客户端在单独的(非 AWT)线程中向服务器发送消息。响应被捕获为 String,转换为 Document 对象,此时获取根元素:
Element root = response.getDocumentElement();
这个根元素然后被传递到排行榜屏幕,因此:
Leaderboard leaderboard = ScreenCache.getLeaderboard();
if (!leaderboard.isVisible())
return;
leaderboard.buildTablesFromResponseLater(root);
然后我调用 AWT 线程,因为我将使用数据以各种方式(更新表等)重新绘制屏幕,并且 Swing 不是线程安全的。我还在某处读到 DOM 的东西不是线程安全的(尽管我现在再也找不到它了)。
public void buildTablesFromResponseLater(final Element root)
Runnable updateRunnable = new Runnable()
@Override
public void run()
buildTablesFromResponse(root);
;
SwingUtilities.invokeLater(updateRunnable);
在 buildTablesFromResponse 中,我开始解析 XML。我从中得到了各种属性,然后我调用了以下代码:
NodeList children = root.getElementsByTagName(TAG_ROOM_STATS);
int length = children.getLength(); <- NPE HERE
但是,这会产生如下所示的 NPE:
10/05 23:44:14.505 java.lang.NullPointerException
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.nextMatchingElementAfter(Unknown Source)
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.item(Unknown Source)
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.getLength(Unknown Source)
at online.screen.g.d(Leaderboard.java:370)
at online.screen.g.c(Leaderboard.java:364)
at online.screen.g.b(Leaderboard.java:315)
at online.screen.g.a(Leaderboard.java:312)
at online.screen.g$4.run(Leaderboard.java:305)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(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$1.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)
我看不出我在这里做错了什么。还有很多其他地方我可以像这样解析 XML,它工作正常,正如我所说,即使是排行榜,这个问题也很少见。我能想到的唯一区别是:
排行榜消息可能比其他消息“更大”。 其他地方几乎肯定会在打开套接字的同一线程中获取 NodeList/length,这将是一个非 AWT 线程。但是,我会认为这会更容易出现问题而不是更少!如果 AWT 线程出现了问题,那么在调用 AWT 线程绘制屏幕之前解析 XML 是一种快速修复。我只是不愿意在没有正确理解潜在问题的情况下这样做。
【问题讨论】:
【参考方案1】:显然这是一个非常古老的线程,但如果其他人遇到这个问题...我最近自己遇到了这个问题,经过一些研究,我能找到的唯一建议是,这是因为解析仍在发生当访问器被调用时。所以我想,简单总结一下我的发现,是的,你应该在回调之前完全解析完 XML。
来自这个帖子(https://community.oracle.com/thread/2114086):
这是因为 JAXP 不是线程安全的。需要同步括号或使用线程安全解析器。
【讨论】:
以上是关于NPE 在 NodeList 上调用 getLength()的主要内容,如果未能解决你的问题,请参考以下文章
在包含 NULL 的 ArrayList 上使用 map 时的 NPE
针对 NodeList 调用 Array.prototype.slice 的目的是啥? [复制]
不能在 Xerces 或 Neko 的节点上调用 getElementsByTagName?