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?

在Fragments [duplicate]中调用时,为getSupportActionBar()抑制NPE警告

Java认识NPE问题 - 空指针异常

EnterTransitionCoordinator 在 Android 5.0 中导致 NPE