Pergunta

I am using the GridWorld case study. I seem to have discovered a bug in the provided program. After attempting to create a grid of invalid size through the GUI and closing the error message, whenever I try to do anything with the existing grid, I get a NullPointerException:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at info.gridworld.gui.GUIController$3.mousePressed(GUIController.java:119)
        at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:279)
        at java.awt.Component.processMouseEvent(Component.java:6501)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
        at java.awt.Component.processEvent(Component.java:6269)
        at java.awt.Container.processEvent(Container.java:2229)
        at java.awt.Component.dispatchEventImpl(Component.java:4860)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Component.dispatchEvent(Component.java:4686)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4489)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
        at java.awt.Container.dispatchEventImpl(Container.java:2273)
        at java.awt.Window.dispatchEventImpl(Window.java:2713)
        at java.awt.Component.dispatchEvent(Component.java:4686)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
        at java.awt.EventQueue.access$000(EventQueue.java:101)
        at java.awt.EventQueue$3.run(EventQueue.java:666)
        at java.awt.EventQueue$3.run(EventQueue.java:664)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:680)
        at java.awt.EventQueue$4.run(EventQueue.java:678)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThre ad.java:211)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread. java:128)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre   ad.java:117)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Additionally, I am unable to change the grid to something else, via the provided GUI:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at info.gridworld.gui.WorldFrame.setGrid(WorldFrame.java:237)
        at info.gridworld.gui.MenuMaker$GridConstructorItem.actionPerformed(MenuMaker.java:344)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
        at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
        at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
        at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
        at java.awt.Component.processMouseEvent(Component.java:6504)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
        at java.awt.Component.processEvent(Component.java:6269)
        at java.awt.Container.processEvent(Container.java:2229)
        at java.awt.Component.dispatchEventImpl(Component.java:4860)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Component.dispatchEvent(Component.java:4686)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
        at java.awt.Container.dispatchEventImpl(Container.java:2273)
        at java.awt.Window.dispatchEventImpl(Window.java:2713)
        at java.awt.Component.dispatchEvent(Component.java:4686)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
        at java.awt.EventQueue.access$000(EventQueue.java:101)
        at java.awt.EventQueue$3.run(EventQueue.java:666)
        at java.awt.EventQueue$3.run(EventQueue.java:664)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:680)
        at java.awt.EventQueue$4.run(EventQueue.java:678)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

I think this is a bug in the GridWorld program itself, and not in any code I write, because this seems to happen even when I just launch the program without giving it any code to execute. I've done some investigation and found that for some reason, the grid gets set to null whenever I attempt to change the grid in the GUI, and the grid I try to create is invalid (or any exception happens when creating the grid). Why is the grid getting set to null? Is there a way I can fix this in the provided source code myself?

The build that I am using is GridWorld 1.02 available at GridWorld.info under the "unofficial code" link. The code at the CollegeBoard website is older. I've tested this and it also happens for older releases.

Foi útil?

Solução 2

Here is what happens

The NullPointer Exception happens in Source File GUIController.java as indicated by the stacktrace.

Grid<T> gr = parentFrame.getWorld().getGrid();
Location loc = display.locationForPoint(evt.getPoint());
if (loc != null && gr.isValid(loc) && !isRunning())

gr, which is retreived from getWorld().getGrid() can be null and the if statement does not check gr before calling gr.isValid().

Tracing the Source:

The Grid gets set by the setGrid() method in WorldFrame.java, which does not check its imput, that is, if you call the method with null, it will set the new grid to null.

The setGrid() method is beeing called from MenuMaker.java (line 343)

Grid<T> newGrid = (Grid<T>) invokeConstructor(); 
parent.setGrid(newGrid);

and the invokeConstructor() method returns null on exceptions. This is, where your null comes from

Fix

Make sure that setGrid in WorldFrame.java does not accept null values as parameter.

public void setGrid(Grid<T> newGrid) {
    if (newGrid == null) {
        return;
    }
    // rest of method goes here

An probably better, yet more complex, solution would be, to ensure that invokeConstructor() in MenuMaker.java does not return null. Notifying the GUI and handling the Exception (instead of returning null) would be a more elegant solution.

Hope this helps.

Outras dicas

I looks like you need to check if newGrid is null when calling setGrid(Grid<T> newGrid) on a WorldFrame. I could recreate the issue you described by creating a grid with a negative row or column value. Allowing the grid to get set to null appears to cause NPEs downstream.

Making the following change to the source will fix it. After closing the error message, I was able to create a new grid of valid size as well as use the other GUI features.

WorldFrame.java:

public void setGrid(Grid<T> newGrid)
{
    if (newGrid == null) {  // this is what I added...
        return;
    }

    Grid<T> oldGrid = world.getGrid();
    Map<Location, T> occupants = new HashMap<Location, T>();
    for (Location loc : oldGrid.getOccupiedLocations())
        occupants.put(loc, world.remove(loc));

    world.setGrid(newGrid);
    for (Location loc : occupants.keySet())
    {
        if (newGrid.isValid(loc))
            world.add(loc, occupants.get(loc));
    }

    display.setGrid(newGrid);
    repaint();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top