0

With a LibGDX Game

I have a Lobby Screen From the Lobby Screen I can go to

  Game 1
  Game 2
  Game 3
  Game 4

When I exit Game 1 (for example) I return back to the Lobby Which allows me now to pick Game 3 (for example)

What I'm noticing is the java native memory is growing
When I do Lobby -> Game 1 -> Lobby -> Game 2 - > Lobby -> Game 3 -> Lobby - > Game 4 …

From Lobby I have

switch (selection) {
  case 1: NewStage = new Game1Screen();  break;
  case 2: NewStage = new Game2Screen();  break;
  case 3: NewStage = new Game3Screen();  break;
  case 4: NewStage = new Game4Screen();  break;
}
game.setScreen (NewStage);

This successfully takes me off to the new Game

Now within the Game Screen I have

switch (state) {
   case EXITING:   this.dispose();
                   game.setScreen(Lobby);    <<-- probably causing the memory growth
                   break;
}

I don't think this is completely shutting down the level and thus causing Java Native Memory to grow.

I want to shutdown and completely destroy the Game once it has been exited and we are back at the Lobby.

Daahrien
  • 10,190
  • 6
  • 39
  • 71
NewDev
  • 257
  • 1
  • 5
  • 18
  • I think the problem might be that you never call `dispose()` on your lobby screen when switching to the gamescreens. But later when you switch back to the lobby, you basically will rebuild it completely, because show(), resume() are called again because of setScreen(Lobby). Maybe move all resource loading to the constructor of Lobby? – noone Jan 11 '14 at 22:26
  • Thanks, I'm not seeing the lobby constructor being recalled, In I do see that it just picks up the render() loop on the next cycle, which is cool. How do I dispose() the gamescreens and how would I dispose() the lobby – NewDev Jan 11 '14 at 22:31
  • @NewDev did you solve your problem? Did any of the answers help you? If so please mark it as accepted. This could help others with the same issue. Thanks – Robert P Feb 20 '14 at 10:25

4 Answers4

0

To make sure you throw everything out of memory, you have to call the dispose() method. In there, you call the dispose() method of every object you used inside your screen.

The things you can dispose are Texture, SpriteBatch and etc. You can dispose of Sprites by calling

costumSprite.getTexture().dispose();

if you do all this correctly, there should be no memory leaks.

You can as well implement ways of, if the game crashes, exit. Just like this exemple:

try {
    //The creation of the application
} catch (Exception e) {
    Gdx.app.exit();
    System.out.println(e);
}
Ferdz
  • 1,182
  • 1
  • 13
  • 31
0

You can do some simple things. At first i would log the Memory when switching the Screens like this to see if you are right that the application memory(not the VM!) growth:

static class MySecurityManager extends SecurityManager
{
    public String getCallerClassName(int callStackDepth)
    {
        return getClassContext()[callStackDepth].getName();
    }
}

private static Runtime runtime = Runtime.getRuntime();;
private static final long KILOBYTE = 1024L;
private static MySecurityManager securityManager = new MySecurityManager();

public static long bytesToMegabytes(long bytes)
{
    return bytes / KILOBYTE;
}

public static void CurrentMemoryUsage()
{
    long memory = runtime.totalMemory() - runtime.freeMemory();
    Gdx.app.log("[LOG] " + securityManager.getCallerClassName(2), " Used memory: " + bytesToMegabytes(memory)
            + "kb");
}

Everywhere you call the static Logger.CurrentMemoryUsage() it does automaticaly log the calling class (securityManager.getCallerClassName(2)) and the current memory usage. (Take care this isn't the fastest way to log! Getting the caller class can be slow but this is already the fastest way for it. I think it's really usefull. see how to get the calling class)

After a switch call the Gabagecollector by using the System.gc(). This does a deep gabage collecting which does take some Time so just call it when there is no problem if it does take time. (mapswitch, screenchanges and so on)

The last thing i can recomend to check your memory is using the jconsole.exe from the java sdk. C:\Program Files (x86)\Java\jdk1.7.0_45\bin\jconsole.exe

Start your application in desktop-mode and connect to it with the jconsole and you can see how much RAM and so on it does use. You can even see how much classes are currently created and much more. Take a look at teh graph at your memory while the application is in use to see if it really rises or if you just have the regulare up and downs of the memory. If it does rise take a look at your objects if you do create objects inside of your rendercycle. (jconsole will show you if you create more and more objects) if so, do delete the creation of objects out of your rendercycle. (No new inside of any draw or act or update!)

Hope this does help.

Community
  • 1
  • 1
bemeyer
  • 6,154
  • 4
  • 36
  • 86
  • Thanks, I had done this. The memory shown in jconsole is fine as it rises and falls and definitely drops once I call System.gc() and when I leave game1 and return to the Lobby. However, the memory reported by the OS Task Manager, rises and keeps rising. Thus the question on native memory. JConsole shows low memory usage < 12 Kb while Task Manager memory shows a steady rise never falling of 220 mb and rising – NewDev Jan 13 '14 at 13:19
  • Thats actually the VM not your game than. So i wouldn't care that much about it. The VM does reserve way to much memory than you would need. Maybe try to tune it with VM parameters. (Are you sure with 12kb? that would be really low if you have loaded assets) – bemeyer Jan 13 '14 at 13:40
  • True, but it keeps growing and eventually crashes if you go into and out of game level -> lobby too many times.
    When I start the Jconsole reports 3mb used while task manager says 80mb. But the Jconsole stays around 4 - 8 mb while task manger grows 180, 220, 320, 400, ….. until it crashes.
    – NewDev Jan 13 '14 at 14:01
0

Screens have the method hide() which is called when you set anothe Screen using

game.setScreen(yourScreen);

You have to dispose the following classes manually, if you don't Need them anymore: AssetManager, Bitmap, BitmapFont, BitmapFontCache, CameraGroupStrategy, DecalBatch, ETC1Data, FrameBuffer, Mesh, ParticleEffect, Pixmap, PixmapPacker, ShaderProgram, Shape, Skin, SpriteBatch, SpriteCache, Stage, Texture, TextureAtlas, TileAtlas, TileMapRenderer com.badlogic.gdx.physics.box2d.World So if you use some of them dispose them on hide.

Robert P
  • 9,398
  • 10
  • 58
  • 100
  • Thanks, is there a way to call dispose() and complete erase all traces of the screen, when game.setScreen() is called and I return from the game back to the lobby ? – NewDev Jan 14 '14 at 14:52
  • You want to call Screen.dispose()? i think you can call this manualy in the hide() method. The documentation of libgdx says, that Screen.dispose() is never called automatically. When you dispose() your Game Screen.hide() will be called. So if you don't Need this Screen anymore if you return to Lobby call the dispose() in the hide() Method – Robert P Jan 14 '14 at 15:28
0

It's very libgdx strange policy, especially that I'm android developer.

dispose function declared as hide, but never called from system. Now I see only two ways.

First, as already write before - move all free resources actions at hide, because hide auto called on change screen or close application.

Second, implement owner ScreenAdapter and manual call dispose at hide.

Yura Shinkarev
  • 5,134
  • 7
  • 34
  • 57