NPE在NodeList

时间:2015-05-11 17:59:27

标签: java xml dom nullpointerexception

我使用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 个答案:

答案 0 :(得分:1)

显然这是一个非常古老的线程,但是其他任何人都遇到过这个问题...我最近遇到了这个问题,经过一些研究后我发现的唯一建议就是因为解析仍在发生当访问者被调用时。所以我想,简要总结一下我发现的内容,是的,你应该在回调之前完全解析XML。

来自此主题(https://community.oracle.com/thread/2114086):

  

这种情况正在发生,因为JAXP不是线程安全的。需要同步括号或使用线程安全解析器。