gpt4 book ai didi

java - StackOverflowError 集合::不可修改列表

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:21:06 25 4
gpt4 key购买 nike

我在下面的 StackOverflowError 中发现了一个奇怪的随机错误。它不是确定性的,所以我很难解决这个问题......我有一个 Arraylist 包装到 Collections::unmodifiableList(...),然后使用 for(Val val : myValues )

这怎么可能? Collections 中 UnmodifiableList 实现中的字段都是最终的,因此不能有任何循环依赖(例如 A->B->A))。不,这里也不涉及反射......

java.lang.StackOverflowError
at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1064)
at java.util.Collections$UnmodifiableCollection.iterator(Collections.java:1063)
at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1064)
at java.util.Collections$UnmodifiableCollection.iterator(Collections.java:1063)
at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1064)
at java.util.Collections$UnmodifiableCollection.iterator(Collections.java:1063)
at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1064)
at java.util.Collections$UnmodifiableCollection.iterator(Collections.java:1063)
at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1064)
at com.server.ServerFunction$ServerFunctionResult.evaluateValues(ServerFunctionn.java:562)
at com.server.ServerFunction$ServerFunctionResult.access$300(ServerFunctionn.java:348)
at com.server.ServerFunction.perform(ServerFunction.java:1171)

生成此代码的代码(由于我无法在此处发布实际代码,因此已重写...):

public final static class ServerFunctionResult
{
private final List<String> myValues;
private final boolean myIsProcessed;

public ServerFunctionResult(List<String> values, boolean isProcessed)
{
// Reduce object retention of empty list objects
myValues = values.isEmpty() ? Collections.EMPTY_LIST : Collections.unmodifiableList(values);
myIsProcessed = isProcessed;
}

public ServerFunctionResult evaluateValues()
{
if (!myIsProcessed)
{
for (String s : myValues) // <-- HERE IT THROWS
{
// Process values
}

return new ServerFunctionResult(myValues, true);
}

return this;
}
}

这是 Java 7u51。我试图解决这个问题,但现在我怀疑 JVM 错误......

其他人是否熟悉这个问题?

最佳答案

这是 Java 7u40 中 UnmodifiableCollection 类的代码:

    static class UnmodifiableCollection<E> 
implements Collection<E>, Serializable {
private static final long serialVersionUID = 1820017752578914078L;
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}

....

public Iterator<E> iterator() {
return new Iterator<E>() {
private final Iterator<? extends E> i = c.iterator();
public boolean hasNext() {return i.hasNext();}
public E next() {return i.next();}
public void remove() {
throw new UnsupportedOperationException();
}
};
}

(您应该在 JDK for Java 7u51 中拥有实际的源代码。)

如您所见,当您在不可修改的集合上调用 iterator 时,它会在匿名类上创建一个实例。该类的构造函数调用 c.iterator() ... 其中 c 是包装类。然而,堆栈跟踪暗示 c 本身是一个不可修改的集合。

我能想到一个合理的解释:

  • 如果您的应用程序(出于某种原因)将不可修改集合中的不可修改集合包装到 N 层,那么创建迭代器将导致 N * 2 层堆栈帧。对于足够大的 N,这将导致堆栈溢出。

还有其他可能的解释,涉及使用反射(或字节码工程)来打破类型抽象边界,或假设的 JVM(可能是 JIT 编译器)错误。坦率地说,JVM 错误解释非常难以置信,但如果我怀疑我会从升级到最新的 Java 7 版本开始。 (实际上,无论如何我可能会这样做!7u51 缺少 Java 7 平台上 1 年的安全补丁和错误修复。)

关于java - StackOverflowError 集合::不可修改列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29026487/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com