Java NPE在节点列表上调用getLength()

Java NPE在节点列表上调用getLength(),java,xml,dom,nullpointerexception,Java,Xml,Dom,Nullpointerexception,我使用org.w3c.dom.Document接口解析在客户端和服务器之间传递的XML消息。我偶尔会遇到一个我无法解释的NPE 事件链如下:客户端在一个单独的(非AWT)线程中向服务器发送消息。响应被捕获为一个字符串,转换为一个文档对象,在该对象上获得根元素: Element root = response.getDocumentElement(); 该根元素随后被传递到排行榜屏幕,因此: Leaderboard leaderboard = ScreenCache.getLeaderboard

我使用org.w3c.dom.Document接口解析在客户端和服务器之间传递的XML消息。我偶尔会遇到一个我无法解释的NPE

事件链如下:客户端在一个单独的(非AWT)线程中向服务器发送消息。响应被捕获为一个字符串,转换为一个文档对象,在该对象上获得根元素:

Element root = response.getDocumentElement();
该根元素随后被传递到排行榜屏幕,因此:

Leaderboard leaderboard = ScreenCache.getLeaderboard();
if (!leaderboard.isVisible())
{
    return;
}

leaderboard.buildTablesFromResponseLater(root);
然后调用AWT线程,因为我将使用数据以各种方式(更新表等)重新绘制屏幕,Swing不是线程安全的。我也曾在某个地方读到DOM不是线程安全的(尽管我现在无法再找到它)

在buildTablesFromResponse中,我开始解析XML。我从中获得各种属性,然后调用以下代码:

NodeList children = root.getElementsByTagName(TAG_ROOM_STATS);
int length = children.getLength(); <- NPE HERE
我看不出我做错了什么。还有很多其他地方我像这样解析XML,它工作得很好,正如我所说的,即使在排行榜上,这个问题也很少出现。我能想到的唯一区别是:

  • 排行榜信息可能比其他信息更“庞大”
  • 其他地方几乎肯定会在打开套接字的同一线程中获得NodeList/length,这将是一个非AWT线程。然而,我认为这会更容易出现问题,而不是更少

如果问题出在AWT线程上,那么在调用AWT线程绘制屏幕之前解析XML是一个快速解决方案。我只是不愿意在没有正确理解基本问题的情况下这样做。

显然这是一个非常古老的主题,但万一其他人遇到这个问题。。。我最近自己也遇到了这个问题,经过一些研究,我能找到的唯一建议是,这是因为调用访问器时仍在进行解析。所以我想,简单总结一下我的发现,是的,您应该在回电话之前完全完成对XML的解析

从这个线程():

这是因为JAXP不是线程安全的。需要同步括号或使用线程安全解析器

NodeList children = root.getElementsByTagName(TAG_ROOM_STATS);
int length = children.getLength(); <- NPE HERE
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)