Search code examples
javamultithreadingenumsnullpointerexceptionagents-jade

Enum becomes null after call


public Boolean performAction(AppleCollectorAgent agent, data.ActionType action)
{
    if(agent != null && action != null)
    {
        actions.put(agent, action);
    }
    else
    {
        System.out.println("GRID:  "+agent+" performs "+action+" TID: "+Thread.currentThread().getId()+". Time: "+ new Date().getTime());
        System.out.println("Either agent or action was null: "+agent+" - "+action);
    }
}

is called by

ActionType ac = ActionType.ApplePickup;
System.out.println("AGENT: "+myAgent+" going to perform "+ac+" TID: "+Thread.currentThread().getId()+". Time: "+ new Date().getTime());
success = GridWorld.get().performAction((AppleCollectorAgent)myAgent, ac);

This works fine for other values of the enum Action, but for the value Action.PickupApple, actions.put throws a NullPointerException. When I put some println's around to display the values for the arguments, it gets even weirder. Before the call, ac is printed as PickApple, and in performAction, action gets printed as null:

GRID:  Agents.GreedyAgent@1a42792 performs null TID: 29. Time: 1296317211796
Either agent or action was null: Agents.GreedyAgent@1a42792 - null
AGENT: Agents.GreedyAgent@1a42792 going to perform ApplePickup TID: 29. Time: 1296317211796

So, how can action become null in performAction?

Some explanation on the background: for a course on multi-agent systems, I have to make a simulation of a gridworld, in which agents can wander around and pick up apples. In each simulation step, each agent can perform one action. The actions types are stored in the enum data.Action. actions is a ConcurrentHashMap, in which each agent stores the Action he wants to do. When all agents have done that, the gridworld processes all that and reports back a Boolean, indicating the success of the action. Each agent has its own thread, as does the gridworld. Further down performAction() there are some syncing mechanisms. I first thought it would be the multithreading that went all wrong, but I think I can safely that that is not the problem. action is null, that is the problem.


Solution

  • Deduced from the comments, I'd say that performAction is being called twice. Especially if it seems to "sometimes" work. Once with action as null, and once with action as PickApple.

    If this is the case, you can use Thread.currentThread().getStackTrace() to work out from where the method is called.