Search code examples
javaswingmemory-leaksthread-sleepinvokelater

JFrame leaking memory?


So today I opened Task Manager and saw that my application leaks 200kbs of memory every second. I looked at my main loop:

public final void run() {
    try {
        Thread.sleep(27);
    } catch (InterruptedException e1) {
        e1.printStackTrace();
    }

    Thread curThread = Thread.currentThread();
    long lastLoopTime = System.nanoTime();
    long OPTIMAL_TIME = 1000000000 / FPS;
    int fps = 0;
    long lastFpsTime = 0;

    while (thread == curThread) {
        if (shouldClose)
        {
            running = false;
            frame.dispose();
            thread = null;
            curThread.interrupt();
            curThread = null;
        }

        long now = System.nanoTime();
        long updateLength = now - lastLoopTime;
        lastLoopTime = now;
        //double delta = updateLength / ((double)OPTIMAL_TIME);

        lastFpsTime += updateLength;
        fps++;

        if (lastFpsTime >= 1000000000) {
            System.out.println("FPS: " + fps + "");
            fpsLabel.setText("FPS: " + fps);
            lastFpsTime = 0;
            fps = 0;
        }

        if (GuiNewProject.createButton.isEnabled() && createProjectDialogIsOpen)
            if (GuiNewProject.folder.getText().length() == 0 || GuiNewProject.projectName.getText().length() == 0)
                GuiNewProject.createButton.setEnabled(false);

        if (!(GuiNewProject.createButton.isEnabled()) && createProjectDialogIsOpen)
            if (GuiNewProject.folder.getText().length() > 0 && GuiNewProject.projectName.getText().length() > 0)
                GuiNewProject.createButton.setEnabled(true);

        //render();
        fpsDone.setText("FPS: " + fps);

        try {
            if (shouldClose) {
                return;
            }
            else
            {
                Thread.sleep((lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    SwingUtilities.invokeLater(this);
}

And I can't seem to figure out why it keeps leaking memory? Any hints or solution to this memory leak would be helpful!

Regards, tambre


Solution

  • JLabel.setText() calls repaint, which pushes a PaintEvent onto the event queue. Because your loop is stalling the event queue, it grows infinitely. Hence the memory leak.

    (SwingUtilities.invokeLater() runs a Runnable on the EDT. If that runnable never returns, like yours here, then no further events can be processed)