问题
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.
回答1:
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);
}
回答2:
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.
回答3:
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.
回答4:
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
.
来源:https://stackoverflow.com/questions/21068345/exit-screen-causing-java-native-memory-to-grow