stacktrace是什么意思?

时间:2018-01-25 07:15:27

标签: java android

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: dev.game.adventure, PID: 21482
                  java.util.ConcurrentModificationException
                      at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
                      at java.util.LinkedList$ListItr.next(LinkedList.java:888)
                      at dev.game.adventure.Troll.wakeup(Troll.java:32)
                      at dev.game.adventure.Simulation$1.run(Simulation.java:29)
                      at android.os.Handler.handleCallback(Handler.java:789)
                      at android.os.Handler.dispatchMessage(Handler.java:98)
                      at android.os.Looper.loop(Looper.java:164)
                      at android.app.ActivityThread.main(ActivityThread.java:6541)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

我在模拟器中运行一段时间后得到了上面的跟踪。这是什么意思?我该如何解决?我甚至无法复制它,因为它只会在一段时间后发生。这是违法的代码:

thing = i.next();(Troll.java:32)

Class Troll.java

package dev.game.adventure;

import android.os.Handler;
import android.widget.Toast;

import java.util.*;

public class Troll extends WalkingPerson {

    private boolean hasCoke = false;
    private AdventureActivity target;

    Troll(Simulation s, World world, String name, AdventureActivity app) {
        super(s, world, name, R.mipmap.lobgoblin, app);
        this.target = app;
        goTo("Kulverten", target);
    }

    public void wakeup() {

        Person victim = (Person) (place.persons.toArray()[((int) (Math.random() * place.persons
                .size()))]);


        if (victim instanceof Troll) { // Don't commit suicide
        } else {
            say("Victim is " + victim.getName() + ".", target);
            Thing thing;

            for (Iterator<Thing> i = victim.things.iterator(); i.hasNext(); ) {

                thing = i.next();

                if (thing instanceof CocaCola) {
                    hasCoke = true;
                    victim.things.remove(thing);
                    world.update(place, target);
                    say("Now I take your Coca Cola!", target);
                    //TODO: Actually take the drink
                } else {
                    drop(thing.name, target); // drop all items so that the key doesn't end up in heaven
                }
            }

            if (!hasCoke) {
                say("Now I kill you!", target); // TODO: Take all the items of the victim
                //  this.getWorld().playAtPlace(place, "effects/gong");
                final Person victim2 = victim;
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        victim2.goTo("Heaven", target);
                        world.update(victim2.place, target);
                        world.sayAtPlace(victim2.place, "-- Game Over --", target);
                        if (victim2.getName().equals("You")) {
                            target.ag.setBackground(world.getPlace("Heaven").getImage());
                            final Toast toast = Toast.makeText(target.ag.getContext(), "GAME OVER!\n", Toast.LENGTH_LONG);// duration);
                            toast.show();
                        }

                    }
                }, 1500);
            }
        }
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(Math.random() > 0.3)
                    go(place.randomDoor(), target);
            }
        }, 2500);
        s.wakeMeAfter(this, (80 + Math.random() * 1000));
    }
}

2 个答案:

答案 0 :(得分:1)

替换:

victim.things.remove(thing);

使用:

i.remove();

从正在迭代的列表中删除项目的唯一安全方法是使用迭代器。

如果使用list.remove()方法执行此操作,迭代器很难更新其内部状态以正确处理删除。因此,它只是放弃了#34; - 它会导致ConcurrentModificationException说'#34;我处于无效状态,我无法从此恢复&#34;。

顺便说一句,我认为你偶尔看到这个的原因是因为列表中的项目排序。

hasNextLinkedList.Itr的实施只会检查:

return nextIndex < size;

其中nextIndex是迭代器的成员变量,在next()中更新为要返回的下一个元素的索引。

如果您移除包含list.remove的项目,则size会减少。因此,如果您使用list.remove删除的项目恰好是列表中的最后一项(或倒数第二项),hasNext()为假,那么您就不会调用next()并获得CME。

值得注意的是,如果你确实删除了倒数第二个元素,那么循环会在处理列表中的最终项之前中断,没有任何异常。这是一种阴险的行为,并且会成为一个真正令人头疼的问题。只需通过迭代器从列表中删除它就可以避免它。

答案 1 :(得分:1)

您可以通过以下方式简单地重现此异常:

ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,5));
Iterator<Integer> iter = list.iterator();
list.remove(0);
iter.next();

基本上,您不能使用迭代器迭代列表,同时从列表中删除内容。

// 1. you have an iterator here
for (Iterator<Thing> i = victim.things.iterator(); i.hasNext(); ) {

    // 3. on the next iteration, you read from i and BOOM!
    thing = i.next();

    if (thing instanceof CocaCola) {
        hasCoke = true;
        // 2. you removed a thing here
        victim.things.remove(thing);
        world.update(place, target);
        say("Now I take your Coca Cola!", target);
        //TODO: Actually take the drink
    } else {
        drop(thing.name, target); // drop all items so that the key doesn't end up in heaven
    }
}

要实际删除内容,您应该在迭代器上调用remove

i.remove() // replace things.remove with this