J'utilise google version Gauva 11.0.1 et ont ce morceau de code:Immutable.listCopyfOf jette ArrayIndexOutOfBoundsException
ImmutableList.copyOf(items);
Lorsque des articles est une ConcurrentLinkedQueue. Je vois parfois cette erreur:
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)
Étant donné que le problème réside entièrement dans la bibliothèque de goyave, quelqu'un sait-il pourquoi?
Mise à jour sur la base réponse ci-dessous
Merci pour l'aide de Wolfcastle, je suis parvenu à reproduire le problème en vase clos, en dehors de ma demande.
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);
L'exécution de ce produit le suivant à chaque fois:
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)
Pour résoudre dans ma demande, j'ai trouvé un certain nombre d'options.
Se éloignant de Collections2
En passant de Collections2.transform à Iterables.transform, le problème disparaît.
Déplacement loin de Java 1.5
Bien que cela n'a pas été possible dans ma situation, je l'ai essayé avec Java 1.6 et Java 1.7 et le problème est résolu. Je soupçonne que cela est dû à un changement de mise en œuvre AbstractCollection.toArray() de 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;
}
Copie du ConcurrentLinkedQueue premier
Exécution une transformation sur une collection non-thread-thread est évidemment loin d'être idéale. Si pour une raison quelconque je devais rester avec Collections2.transform, je peux résoudre le problème en prenant une copie de la collection d'items en premier.
Qu'est-ce que 'items' dans ce cas?Pouvez-vous poster un programme court mais complet démontrant le problème? –
Le paramètre 'size()' de la propriété 'ConcurrentLinkedQueue' n'est pas nécessairement le même pendant toute la durée de la liste immuable (pour créer le tableau et lire les valeurs). – kiheru
Salut Jon - J'essaye actuellement de produire un exemple isolé qui reproduit ceci et posterai si et quand je peux faire cela. Je suis également tenté de passer à une version plus récente de la goyave, au cas où cela serait utile. Je me doute qu'il peut être dû à essayer de copier un Iterable qui est mis à jour en même temps. – imrichardcole