-2
\$\begingroup\$

I have a level manager for my game I'm working on, and it's supposed to unload the previous level, and then load the next level. However, when I test it (though I'm not sure I'm testing it right) the memory usage seems to go up when I switch levels multiple times.

public final class LevelManager implements KeyControllable {

    private LevelList levels;
    private int currentLevel;

    public LevelManager(final int width, final int height) {
        levels = new LevelList(width, height, this);
        currentLevel = 0;
    }

    public void goToLevel(final LEVEL level) {
        levels.unloadLevel(currentLevel);
        for (int i = 0; i < LEVEL.values().length; i++) {
            if (LEVEL.values()[i] == level) {
                currentLevel = i;
            }
        }
        levels.getLevel(currentLevel).reset();
    }

    public void draw(final Graphics2D g) {
        levels.getLevel(currentLevel).draw(g);
    }

    public void update() {
        levels.getLevel(currentLevel).update();
    }

    @Override
    public void keyPressed(final KeyEvent e) {
        if (levels.getLevel(currentLevel) instanceof KeyControllable) {
            ((KeyControllable) levels.getLevel(currentLevel)).keyPressed(e);
        }
    }

    @Override
    public void keyReleased(final KeyEvent e) {
        if (levels.getLevel(currentLevel) instanceof KeyControllable) {
            ((KeyControllable) levels.getLevel(currentLevel)).keyReleased(e);
        }
    }

    public enum LEVEL {
        LEVEL_ONE(LevelOne.class), LEVEL_TWO(LevelOne.class);

        Constructor<? extends AbstractLevel> level;

        private LEVEL(final Class<? extends AbstractLevel> level) {
            try {
                this.level = level.getDeclaredConstructor(int.class, int.class, LevelManager.class);
            } catch (NoSuchMethodException | SecurityException e) {
                e.printStackTrace();
            }
        }
    }

    private static class LevelList {
        private AbstractLevel[] levels;

        final private int width, height;
        final private LevelManager levelManager;

        public LevelList(final int width, final int height, final LevelManager levelManager) {

            this.width = width;
            this.height = height;
            this.levelManager = levelManager;

            LEVEL[] levelList = LEVEL.values();
            levels = new AbstractLevel[levelList.length];
        }

        public void unloadLevel(int i) {
            levels[i] = null;
        }

        public AbstractLevel getLevel(final int i) {
            if (levels[i] == null) {
                try {
                    levels[i] = LEVEL.values()[i].level.newInstance(width, height, levelManager);
                } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                        | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
            return levels[i];
        }
    }
}

I was using this to test the used memory:

System.out.println(Runtime.getRuntime().totalMemory());

Is there a memory leak in this program? (other tips would be appreciated as well)

\$\endgroup\$

closed as off-topic by tim, syb0rg, nhgrif, mleyfman, Jamal Aug 20 '14 at 23:10

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions containing broken code or asking for advice about code not yet written are off-topic, as the code is not ready for review. Such questions may be suitable for Stack Overflow or Programmers. After the question has been edited to contain working code, we will consider reopening it." – tim, syb0rg, nhgrif, mleyfman, Jamal
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    \$\begingroup\$ If this code is not functioning then it may be off-topic for Code Review. It might be better to edit the question to include the code to review without specifically asking for reviewers to fix the memory leak. \$\endgroup\$ – bazola Aug 20 '14 at 20:18
  • 1
    \$\begingroup\$ I agree with @bazola, you are mainly asking how to find (and possibly fix) a bug in your code, which is off topic here. It might be on topic at stackoverflow (tag memory-leaks) \$\endgroup\$ – tim Aug 20 '14 at 21:42
2
\$\begingroup\$

Java memory management is not deterministic. You cannot say for sure when a batch of memory that was allocated to an object is unloaded. Ensure that all references to that level are disposed of - that's all you can really do.

You could also try storing your levels as a WeakReference<T> inside of your level list. The downside of this means your levels becoming immediately available for garbage collection once they are no longer referred to anywhere in your program which could become an issue if you will be granting the user the option to go back to previous levels.

Remember, though; premature optimization is the root of all evil. You don't need to consider this until it becomes an issue (has a performance impact on your game).

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.