Android - OutOfMemoryError

Hey guys. Im working on a Android app for a client, but have run into some problems.



Here’s the problem:

We have five 3D models, which is about 6MB each (j3o), which is weird, cause the original 3DS file is only 1.3MB.

I can load the first one up just fine, and it will show perfectly. But when loading the next one, the phone runs out of memory (on my own Galaxy Nexus, it only happens after changing model 2-3 times)

Anyways, I tried doing some unloading of the current model first, but it doesn’t seem to be working.



Here’s the Callable I use to load the next model:

[java]

public static class LineLoader implements Callable<Integer> {

String lineName;



public LineLoader(String name) {

lineName = name;

}



@Override

public Integer call() throws Exception {

while (modelCar != null) {

modelCar.detachAllChildren();

modelCar.removeFromParent();

modelCar = null;

}

Log.e(“LineLoader”, "Loading Model: " + lineName);

modelCar = (Node) assetManager.loadModel(lineName);

Log.e(“LineLoader”, "Loading Done: " + lineName);

modelCar.setLocalRotation(new Quaternion().fromAngles(-1.57079633f, 0, 0));

modelCar.scale(0.03f);



modelCar.getChild(5).setMaterial(assetManager.loadMaterial(“assets/materials/clearglass.j3m”));

modelCar.getChild(9).setMaterial(assetManager.loadMaterial(“assets/materials/windowglass.j3m”));

modelCar.getChild(10).setMaterial(assetManager.loadMaterial(“assets/materials/redglass.j3m”));



modelCar.getChild(5).setQueueBucket(RenderQueue.Bucket.Transparent);

modelCar.getChild(9).setQueueBucket(RenderQueue.Bucket.Transparent);

modelCar.getChild(10).setQueueBucket(RenderQueue.Bucket.Transparent);



carNode.attachChild(modelCar);

return null;

}

}

[/java]

As you can see I detach all children fron the current one, then I remove it from its parent (which is a car node, which also contains the wheels)

And then I set it to null, as the garbage collector should grab it then.



Anyways, I’ve noticed that when loading the next model the garbage collector is running.

Theres a specific line it throws out right after its done loading, but that only happens when the loading crashes with OutOfMemory

[java]

03-02 16:23:48.420: I/dalvikvm-heap(20305): Forcing collection of SoftReferences for 8380432-byte allocation

[/java]



Anyways, I just want to ask if there is a way to force-remove a node from memory before continuing?



Regards, MrAdam.

You say the models are 6mb ea.

If you dont have a really good special phone, then your phone can take up to about 1 GB in temp memory.

So you exceed it by loading the second model which requires 1.2GB.

Do you know for a fact that the first node isn’t getting garbage collected? I’d recommend using DDMS (http://developer.android.com/guide/developing/debugging/ddms.html) in the Android SDK to look at memory allocation. It can give you a really good picture of what’s going on at a given snapshot, though I doubt you’ll be able to catch it at the exact moment it’s running out of memory.



As for the debug message about SoftReferences, that’s to be expected – the VM is throwing ballast overboard to try to make room for a big allocation.

It is getting garbage collected. At least some of it…

But after changing models a few times it runs out of memory.



I was just wondering if there was a way to specifically remove a certain model from the memory

If a model isn’t used in an onscreen Geometry and there are no other references to it being held, then it should get garbage collected.



Try the DDMS stuff, really. The heap profiler tool can show you every object in the heap (including your model) and tell you what other objects are holding references to it. That’ll let you zero in on the problem pretty quickly.

I just wanna tell you that I fixed the problem.

my LineLoader to load the 3D model. I removed the call to it when the application launches,

and moved it into the simpleapplication itself. So it wont load the model until the user reaches the jme application.

Anyways, I can now change model like crazy, and it wont run out of memory.

@mradam said:
I just wanna tell you that I fixed the problem.
my LineLoader to load the 3D model. I removed the call to it when the application launches,
and moved it into the simpleapplication itself. So it wont load the model until the user reaches the jme application.
Anyways, I can now change model like crazy, and it wont run out of memory.

Didn't fix it :/ I think the problem lies in the BinaryImporter, which loads up the whole thing in memory.
Ive tried using piped threads instead, but it still uses up too much memory..
[java]int size = -1;
byte[] cache = new byte[4096];
while((size = bis.read(cache)) != -1) {
baos.write(cache, 0, size);
if (listener != null) listener.readBytes(size);
}[/java]
This is where it always runs out of memory, baos.write()

If any of you got some way to optimize this for low-memory devices like android phones, please do tell.
Also, another thing I've noticed is that the original 3ds file is 1.3 mb, where the converted j3o file is about 6 mb.