我使用谷歌gauva 11.0.1版,並有這段代碼:Immutable.listCopyfOf拋出ArrayIndexOutOfBoundsException異常
ImmutableList.copyOf(items);
如果項目是的ConcurrentLinkedQueue。我偶爾看到這樣的錯誤:
java.lang.ArrayIndexOutOfBoundsException: 10
at java.util.AbstractCollection.toArray(AbstractCollection.java:126)
at com.google.common.collect.ImmutableList.copyFromCollection(ImmutableList.java:278)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:247)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:217)
鑑於這個問題完全在於番石榴庫中,沒有人知道爲什麼嗎?基於以下
感謝您的Wolfcastle幫助正確答案
更新,我設法重現問題孤立,我的應用程序之外。
final int itemsToPut = 30000;
final ConcurrentLinkedQueue<Integer> items = new ConcurrentLinkedQueue<Integer>();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < itemsToPut; i++) {
items.add(i);
}
}
}, "putter-thread").start();
final Iterable<String> transformed = Collections2.transform(items, new Function<Integer, String>() {
public String apply(Integer integer) {
return "foo-" + integer;
}
});
ImmutableList.copyOf(transformed);
運行此產生以下每次:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 21480
at java.util.AbstractCollection.toArray(AbstractCollection.java:126)
at com.google.common.collect.ImmutableList.copyFromCollection(ImmutableList.java:278)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:247)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:217)
要在我的應用程序解決,我發現了一些選項。
從Collections2
搬走通過切換從Collections2.transform到Iterables.transform,問題消失。
從Java 1.5
雖然這搬走是不可能在我的處境,我與Java 1.6和Java 1.7嘗試過了,問題解決了。我懷疑這是由於在實施AbstractCollection.toArray()1.5的變化:
1.5
public Object[] toArray() {
Object[] result = new Object[size()];
Iterator<E> e = iterator();
for (int i=0; e.hasNext(); i++)
result[i] = e.next();
return result;
}
1.6
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
複製的ConcurrentLinkedQueue第一
表演對非線程安全集合的轉換顯然遠非理想。如果由於某種原因我不得不繼續使用Collections2.transform,我可以通過首先獲取items集合的副本來解決問題。
在這種情況下,「物品」是什麼?你能發佈一個簡短但完整的程序來證明問題嗎? –
ConcurrentLinkedQueue的'size()'在不可變列表需要它的時候(用於創建數組並讀取值)不一定相同。 – kiheru
嗨喬恩 - 我目前正試圖產生一個孤立的例子,再現這一點,並會發布如果當我可以做到這一點。如果有幫助,我也想升級到更高版本的番石榴。我懷疑它可能是由於試圖複製同時更新的Iterable。 – imrichardcole