解释java堆栈跟踪时遇到问题

解释java堆栈跟踪时遇到问题,java,indexoutofboundsexception,Java,Indexoutofboundsexception,我有一个堆栈跟踪,我需要一些帮助来解释: java.lang.ArrayIndexOutOfBoundsException: 36 >= 36 at java.util.Vector.elementAt(Vector.java:427) at javax.swing.tree.VariableHeightLayoutCache.getNode(VariableHeightLayoutCache.java:976) at javax.swing.tree.Variab

我有一个堆栈跟踪,我需要一些帮助来解释:

java.lang.ArrayIndexOutOfBoundsException: 36 >= 36
    at java.util.Vector.elementAt(Vector.java:427)
    at javax.swing.tree.VariableHeightLayoutCache.getNode(VariableHeightLayoutCache.java:976)
    at javax.swing.tree.VariableHeightLayoutCache.getPreferredHeight(VariableHeightLayoutCache.java:274)
    at javax.swing.plaf.basic.BasicTreeUI.updateCachedPreferredSize(BasicTreeUI.java:1823)
    at javax.swing.plaf.basic.BasicTreeUI.getPreferredSize(BasicTreeUI.java:1924)
    at javax.swing.plaf.basic.BasicTreeUI.getPreferredSize(BasicTreeUI.java:1912)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1642)
    at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
    at java.awt.Container.layout(Container.java:1420)
    at java.awt.Container.doLayout(Container.java:1409)
    at java.awt.Container.validateTree(Container.java:1506)
    at java.awt.Container.validate(Container.java:1479)
    at javax.swing.RepaintManager$2.run(RepaintManager.java:698)
    at javax.swing.RepaintManager$2.run(RepaintManager.java:696)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
    at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:695)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1679)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:715)
    at java.awt.EventQueue.access$400(EventQueue.java:82)
    at java.awt.EventQueue$2.run(EventQueue.java:676)
    at java.awt.EventQueue$2.run(EventQueue.java:674)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:685)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
堆栈中没有一个文件或函数是为我的程序准备的,所以据我估计,它必须是swing的100%内部文件。但这并不是说这可能不是我的程序的错

我可以大致了解JVM当时在做什么——看起来它正在重新绘制滚动窗格中的一个JTree组件(我有几个,所以我不知道它可能是哪个)

关于可能导致此错误的原因,我的最佳猜测是,树的内容(以及其中的节点数)在重新绘制期间的某个点发生变化,因此存储子节点的向量在获取组件大小的过程中会发生大小变化

这听起来可信吗

如果是这样的话,我怎样才能逃避呢?我想我应该在任何更新正在进行时阻止重新绘制,或者相反,在任何重新绘制正在进行时阻止更新?

Swing“在更新正在进行时阻止重新绘制”的正常方式是将对UI的任何更改限制在事件分派线程中;如果你不知道(或者程序作者不知道/不知道)那是什么,这表明你是问题的一部分

错误消息(顺便说一句,我觉得没有什么好笑的)是说有一个向量(编写Swing时没有出现泛型集合)包含36个元素,索引为0-35;代码试图访问此向量的索引36,因此出现异常

我会寻找在任何情况下都会发生变化的UI部分——是数据变化、窗口大小调整,还是什么?向量有36个元素这一事实应该会给你一些线索——你有没有一个地方有那么多的按钮,或者什么类型的?我想它也可能是一个包含36个组件的窗口;UI是否有一个组件从窗口消失的位置


在同一个区域中,我将寻找一些调用事件分派线程之外的类似paint或repaint的代码——所有这些代码都必须在该线程中完成。查看SwingUtilities.invokeAndWait()以了解一种不需要对现有代码进行大量修改的方法,如果它需要的话。

请注意,我认为您的假设听起来确实有道理。恐怕无法提供任何规范化解决方案。这可能需要一段时间,但您应该逐步使用调试器,并找出它失败的确切位置。然后根据这一点采取行动info@redFIVE我很想,但不幸的是,这是一份来自客户的报告:(@Majenko,呃,那太差劲了。你有和他们一样的源代码吗?你能复制吗?这个程序是我的,但我似乎还没有出错(现在).我有另一个想法:这些树是从多个不同的来源更新的,可能是两个线程之间发生冲突,两个线程同时更新它?我假设(猜测)这是我的一棵树。它们可以很容易地包含36+个元素。我根本不做任何绘制或重新绘制调用,但我有一些nodeStructureChanged()调用。从多个线程中添加/删除节点的操作很多,包括计时器线程、从EDT派生的线程以及其他地方。天哪!我刚刚遇到了这种情况!这至少是一个帮助,我现在可以复制它了。这是一个“随机”的事情,当它感觉到它时就会发生(程序坐在那里,没有用户交互).好的,谢谢,我想你为我指明了正确的方向。我已将计时器事件包装在SwingUtilities.invokeLater()中我认为它已经解决了这个问题。我猜计时器的EDT和Swing的EDT不一样…!实际上,它已经把问题转移到其他地方了。我现在有了更多的数据,因为它提供的跟踪更有用。它是javax.Swing.tree.DefaultTreeModel.nodeStructureChanged()引发的立即调用。很高兴能提供帮助。如果您还没有遇到它,另一个调试此类问题的工具是SwingUtilities.isEventDispatchThread(),它会告诉您运行调用的线程是否是(UI)事件调度线程。祝您好运。