抛出StackOverFlowError的java.util.Sublist

Bes*_*ces 5 java stack-overflow error-handling

我们在生产中偶尔会遇到与执行SubList操作相关的StackOverFlowError错误.有没有人见过这样的东西,知道是什么原因造成的?

这是被调用的代码,用于触发错误:

  FacesContext context = FacesContext.getCurrentInstance();
    String newViewID = context.getViewRoot().getViewId();

    if (newViewID != null) {
     if (breadCrumbs.contains(newViewID)) {
      // Trims the list upon going back to allow for multiple back button requests.  
      // This is lightweight and not intended for a complex circular navigation.
      breadCrumbs = breadCrumbs.subList(0, breadCrumbs.indexOf(newViewID) + 1);
     } else {
      breadCrumbs.add(newViewID);
     }
    }
Run Code Online (Sandbox Code Playgroud)

结果 :

Caused By: java.lang.StackOverflowError
 at java.util.SubList$1.<init>(AbstractList.java:688)
 at java.util.SubList.listIterator(AbstractList.java:687)
 at java.util.SubList$1.<init>(AbstractList.java:688)
 at java.util.SubList.listIterator(AbstractList.java:687)
 ...
Run Code Online (Sandbox Code Playgroud)

Jim*_*son 6

subList()方法返回由原始列表支持的视图.

根据javadoc:

如果支持列表(即此列表)在结构上以除返回列表之外的任何方式进行修改,则此方法返回的列表的语义将变为未定义.(结构修改是那些改变了这个列表的大小,或以其他方式扰乱它的方式,正在进行的迭代可能会产生不正确的结果.)

您正在对列表进行结构更改,因此所有投注都会关闭 - 任何事情都可能发生,包括无限递归,这似乎正在发生.

  • 换句话说,你应该这样做:`breadCrumbs = new ArrayList(breadCrumbs.subList(0,breadCrumbs.indexOf(newViewID)+ 1));` (3认同)

Bes*_*ces 0

该问题是由于 breadCrumbs 是一个 LinkedList 引起的——我们向 LinkedList 添加了太多项目,并且调用 subList 暴露了这个问题。