Memory Leak when switching AppStates

Yo!
I’m having trouble with memory leak when changing/switching levels, I’m currently using AppStates for my levels.
Well, it’s working but after a number of transitions, the heap space keeps filling up and doesn’t go down.
I’m detaching all children from the rootNode and recreating the physicsSpace for each level.
I’m using the CollisionShapeFactory to create my level collision shape from my scene model.
I’m pretty sure that a large part of the leak comes from the physicsSpace since the number of transitions that I can
do before the heap space becomes full seems to be affected by the amount of polygon that my scene model uses.
Tried different settings on the JVM, a larger heap space gives more transitions before it gets full but that doesn’t stop it
from filling up until it slows down the game due to continuous GC and eventually crash.

I’ve prepared a little test case if you don’t mind:

Classes in the test case:
Main - the main class
Globals - the class where I store static objects like the assetManager, stateManager, etc. for easier access
Terrain - the factory class that creates the level from the scene model
MapA - extends AbstractAppState, the level is created inside its initialize method
MapB - extends AbstractAppState, the level is created inside its initialize method

With the test case’s current JVM settings(-XX:MaxDirectMemorySize=512M -Xms10m -Xmx256m),
the heap space will be near full at around 40 transitions.

Should I use AppStates as my levels or should I implement another way of level transition?

Any help or suggestions are appreciated! Thanks!

AppStates are not the issue. You can trivially see if your cleanup() methods are being called and then you will know that app states are not the issue. Whatever other mechanism you chose to use would have exactly the same problem because it is not app state related.

Something is not getting released. You need to figure out what that is. A profiler is your best friend in these cases.

Caveat: for the app states you have not written (maybe) they could have a bug where they aren’t freeing up resources on cleanup.

Also, I don’t have time to download a whole project so maybe you could post some info about how you “switch app states” and what you do to cleanup and whether you use the cleanup() method or something else.

Thanks for the reply!
And yes, I’m definitely using the cleanup() method and inside it I do some cleaning for the current level like detaching all children and removing lights from the rootNode
and removing objects from physicsSpace if I ever added some.
Same results when I do it in stateDetached but I’ll go with cleanup().

And by switching AppStates, I do it like, let’s say, for example, inside my MapA that extends AbstractAppState:
stateManager.detach(this) then stateManager.attach(mapB), wherein mapB is also a class that extends AbstractAppState and is instantiated inside mapA’s initialize() method(MapB mapB = new MapB()). Inside my test case, I’ve mapped it into the RETURN_KEY to switch AppStates.

To show exactly how I do it, you might want to download the linked file, it’s barely 2mb in size(half of it coming from a png file that I use) with 5 small classes, much like a testbed
or I could just post the code here If you prefer viewing it like that.

Also, I’ve tried using the profiler(that’s where I view the heap space), what’s noticeable is the great amount of javax.vecmath.Vector3f it allocates, I suppose it has something to do with 3D objects/physics objects in the scene? Or I’m probably just doing it wrong?

The Vector3fs aren’t interesting on their own… it’s what is referencing them that’s interesting.

Anyway, your app states are working fine. I’d say maybe the asset manager cache but if you are just going back and forth between levels then you should be reusing the cache stuff. You could try temporarily leaving all physics related stuff out and see how many switches you can do before running out of memory… at least to rule it in or rule it out as something to look deeper into.

1 Like

@totiman9 You can use JVisualVM to find the object(s) referencing a given Vector3f.
Let’s say it’s a Node, that might still not be the real object keeping that Vector3f alive, so keep going up the referrer chain until you find an object that you know whether it should be alive or not.
If it’s legitimately alive, try starting at another Vector3f. If it should have been removed, find out why it wasn’t removed and fix that bug :slight_smile:
(For me, in most cases, it was some library that kept holding a reference because it expected me to call some cleanup method that wasn’t clearly documented. Second on list were simple bugs in library code, then my own code - probably because there’s so much more library code than my own code in the application.)

1 Like
@toolforger said: @totiman9 You can use JVisualVM to find the object(s) referencing a given Vector3f. Let's say it's a Node, that might still not be the real object keeping that Vector3f alive, so keep going up the referrer chain until you find an object that you know whether it should be alive or not. If it's legitimately alive, try starting at another Vector3f. If it should have been removed, find out why it wasn't removed and fix that bug :-) (For me, in most cases, it was some library that kept holding a reference because it expected me to call some cleanup method that wasn't clearly documented. Second on list were simple bugs in library code, then my own code - probably because there's so much more library code than my own code in the application.)

I don’t know if JVisualVM is the one easily added as a plug-in from the SDK… but the SDK profiler can do all of these things also.

…just in case they are different things, I thought I’d point that out. I don’t know what the SDK profiler is other than “that plugin I checked” but it is a full featured profiler.

JVisualVM comes as part of the JDK, so it’s available to any Java developer without further installation :slight_smile:
Essential for us Eclipse types.
SDK users can probably use the SDK profiler, I’d expect it to use the exact same JVM debug interface as JVisualVM.

It might be a good idea just to fire up JVisualVM anyway, just to see whether it has anything to offer that the SDK is missing out on, and whether it’s relevant.
If nothing else, it gives you an idea how much of what you see is done by the JVM and how much is done by the SDK - that knowledge can be helpful to decide whether some misbehaviour is due to SDK or JVM.

avctually jvisualvm is just the standalon of the netbeans profile stuff no?

@Empire Phoenix said: avctually jvisualvm is just the standalon of the netbeans profile stuff no?
Yep. Its actually coming from the NB foundation and is now part of the JVM ;)

@pspeed You’re right, the AssetManager is the culprit, I’ve managed to fix the leak by avoiding the use of a static AssetManager directly
to create my levels and other entities and instead just pass it to the constructor of my classes that needs it.
It’s like a big thorn cleared out of my throat, I’ve even developed a technique to optimize my scene a lot, and I mean A LOT to consume memory as low as possible.
Well, nightmare’s over, at least for now.
Thanks a lot guys!

Hello, I know this post is old, but I found it and I seem to be having a similar problem. I read what your solution was and it sounds very straight forward, but could you explain to me what it was you did? I’m very new to Jme3 and programming as a whole and as such even the simplest of things can seem a bit confusing. I reiterate that I know this post is old, so any response at all will be greatly appreciated. Thank you.