Games are resource heavy applications. Images and sound effects can take up a considerable amount of RAM. Also, most of these resources are not managed by the Java garbage collector. Instead they are managed by native drivers. Having the garbage collector decide when to release a 5 megabyte texture from video ram wouldn’t be a too bright idea either. Disposable interface which indicates that instances of this class need to be disposed of manually at the end of the life-time. Failure to dispose resources will lead to severe memory leaks!. click here instead for the full list):
- -
Resources should be disposed of as soon as they are no longer needed, freeing up memory associated with them. Accessing a disposed resource will result in undefined errors, so make sure to clear out all references you have to a disposed resource.
dispose()method which implemented fromDisposableinterface ofcom.badlogic.gdx.utils. If it does, you are now working with a native resource.implements Disposable. It will show you result of all source files (thus class) you need to calldispose()when you’re done with it. Note that all other classes that extend from such result classes are also applicable. List above is already complete. Note that a few classes from result come from test class of libGDX itself which are not relevant to your interest.Object pooling
Object pooling is the principle of reusing inactive or “dead” objects, instead of creating new objects every time. This is achieved by creating an object pool, and when you need a new object, you obtain it from that pool. If the pool has an available (free) object, it is returned. If the pool is empty, or does not contain free objects, a new instance of the object is created and returned. When you no longer need an object, you “free” it, which means it is returned to the pool. This way, object allocation memory is reused, and garbage collector is happy. This is vital for memory management in games that have frequent object spawning, like bullets, obstacles, monsters, etc. libGDX offers a couple tools for easy pooling.
- Poolable interface
- Pool
- Pools
Poolableinterface means you will have areset()method in your object, which will be automatically called when you free the object. Below is a minimal example of pooling a bullet object.
In your game world class:public class Bullet implements Pool.Poolable { public Vector2 position; public boolean alive; /** * Bullet constructor. Just initialize variables. */ public Bullet() { this.position = new Vector2(); this.alive = false; } /** * Initialize the bullet. Call this method after getting a bullet from the pool. */ public void init(float posX, float posY) { position.set(posX, posY); alive = true; } /** * Callback method when the object is freed. It is automatically called by Pool.free() * Must reset every meaningful field of this bullet. */ @Override public void reset() { position.set(0,0); alive = false; } /** * Method called each frame, which updates the bullet. */ public void update (float delta) { // update bullet position position.add(1*delta*60, 1*delta*60); // if bullet is out of screen, set it to dead if (isOutOfScreen()) alive = false; }}
Pools class provides static methods for dynamically creating pools of any objects (using ReflectionPool and black magic). In the above example, it could be used like this.public class World { // array containing the active bullets. private final Array<Bullet> activeBullets = new Array<Bullet>(); // bullet pool. private final Pool<Bullet> bulletPool = new Pool<Bullet>() { @Override protected Bullet newObject() { return new Bullet(); } }; public void update(float delta) { // if you want to spawn a new bullet: Bullet item = bulletPool.obtain(); item.init(2, 2); activeBullets.add(item); // if you want to free dead bullets, returning them to the pool: Bullet item; int len = activeBullets.size; for (int i = len; --i >= 0;) { item = activeBullets.get(i); if (item.alive == false) { activeBullets.removeIndex(i); bulletPool.free(item); } } }}
private final Pool<Bullet> bulletPool = Pools.get(Bullet.class);
How to Use Pool
Pool<>manages a single type of object, so it is parameterized by that type. Objects are taken from a specificPoolinstance by invokingobtainand then should be returned to the Pool by invokingfree. The objects in the pool may optionally implement the interface (which just requires areset()method be present), in which case thePoolwill automatically reset the objects when they are returned to the pool. By default, objects are initially allocated on demand (so if you never invokeobtain, the Pool will contain no objects). It is possible to force thePoolto allocate a number of objects by callingfill()after instantiation. Initial allocation is useful to have control over when these first time allocations occur.Pool<>because thenewObjectmethod is abstract.Pool Caveats
Beware of leaking references to Pooled objects. Just because you invoke “free” on the Pool does not invalidate any outstanding references. This can lead to subtle bugs if you’re not careful. You can also create subtle bugs if the state of your objects is not fully reset when the object is put in the pool.Profiling Memory leaks
VisualVM (free) and JProfiler (trial/paid) prove useful in tracking down the issue. These memory profilers will tell you what type of object is eating up the memory. From there on you can start tracking down the leak.
