OutOfMemoryExceptions - Gotta free memory!

I’ve built a 2D-gameengine for classical games such as SuperMario or similar where you can define several “levels” as different GameSlides where each gameslide has neighbouring gameslides and so on.

The same concept as when playing Diablo I / II and you walk out from the village and you have to “load the next level”.

Which brings me to the question:

This loading between gameslides works well enough for smaller games, but I just made my own Zelda-style game with quite big background images and suddenly I get a OutOFMemoryException (due to the big background I suppose) :confused: Therefor I have to deallocate the allready loaded stuff when I change slide and THAT’s the question…

I chech the available memory using Runtime freeMemory() / availableMEmory() / totalMemory() and nomatter what I try, it just won’t deallocate and free the previous slides…

How do I manually remove stuff from the heap?
(much text for a trivial question, but I hope you get my point)

/Markus

Hi
You can’t. The garbage collector will in theory run through when it feels like it, this might coinside with the vm realising it hasn’t got enough memory to do what you ask it too. Have you tried setting the heap size with vm flags?, this may give it a chance to load the next level in, then whilst your playing, the gc might kick in, if it feels like it.

HTH

Endolf

afaik garbage collection is done before an outofmemory exception is thrown (and when it feels like dooing so).

if changing heap size doesnt help you might have some references to unneeded pictures lying around somwhere, and so preventing their collection.

“System.gc()” will run the garbage collector.

How big is your background image? Some time ago I had problem loading 1024*1024 images. It turned out that it was impossible to allocate 4 meg of mem in one chunk. But this was an older vm.

Another tip is to allocate memory more slowly. Throw in some sleeps between big allocations might help. But this is of course just a debugging tip, not a solution.

Turn on GC profiling so you KNOW when objects are collected.

java -verbose:gc MyMainClass
or
java -Xloggc: MyMainClass
or
java -Xrunhprof:<some fancy options - look it up on java.sun.com>

It sounds like Smoke has the most likely answer - you still have references to the older images so they aren’t “garbage” that can be collected. You won’t get an out of memory error unless the heap really is full of objects that can still be reached.

[quote]“System.gc()” will run the garbage collector.

Another tip is to allocate memory more slowly. Throw in some sleeps between big allocations might help. But this is of course just a debugging tip, not a solution.
[/quote]
System.gc() will PROBABLY run the garbage collector, but it could just as well do absolutely nothing. I’ve seen some interesting reports on how it should be used. One paper says they got the best performance if it was called at regular intervals so not a lot of garbage could ‘build up’. Sun folks have said in general you shouldn’t worry about calling it at all and the VM will likely do the right thing.

Sleeps should NOT help - true they might give the GC time to run, but whenever you attempt to allocate some memory and the free space isn’t immediately available on the heap, the GC is REQUIRED to run and reclaim all garbage before reporting out of memory. So it doesn’t matter if it got a chance to run before that or not.

Another possible cause would be if you were using a VM that didn’t have a compacting gc; and you were getting memory fragmentation.

Its unlikely to be the cause though - I’ve only ever come across 1 VM that suffered from this problem - The Siemens J2ME VM on the SL45 and M50 mobile phones.

Big thanx to all of you! You’re fast and informative replies are the reason for why I’ve come to love this forum :smiley:

When thinking of it, I know that I have references laying around which prevents the gc from collecting… The problem of how ( in a general manner) to deal with this is another issue that I’ll try to master tomorrow :wink:

Anyway - Interesting thoughts came to my head:
The background image is quite big - 3200x2500 px and is used as a scrolling background for my Zelda-look-alike game that happens to be an Applet which brings me to my next question:

How can I apply all the switches that you’re refering to in your replies when I don’t develope appz? I assume that the switches can be applied to “appletviewer”?

BTW - I ran JProfiler on my game and looked at the heap usage – Is it normal to have a triangular wave of mem.usage? Ideally, I’d like a constant line (after initialization is completed) but I don’t…

Curious!

/Markus

[quote]How can I apply all the switches that you’re refering to in your replies when I don’t develope appz? I assume that the switches can be applied to “appletviewer”?
[/quote]
Yes, exactly. Appletviewer lets you do what you need.

[quote]BTW - I ran JProfiler on my game and looked at the heap usage – Is it normal to have a triangular wave of mem.usage? Ideally, I’d like a constant line (after initialization is completed) but I don’t…
[/quote]
This can happen. Particularly if you generate garbage objects quickly. As pointed out above, the GC will do a full collection when it is forced to because the heap is full. That would be the point where your triangle wave drops down. Then the heap fills up again as you generate more garbage and the cycle happens all over again…
If you generate garbage slower it might only affect the slope of those triangles, but if you have some natural pauses (sleeps) and the GC can take advantage of them you might fins that the GC runs more frequently doing smaller chunks of work. In general you will never get a flat line unless you aren’t generating any new garbage - Something you should try to minimize in an action game. GC - based systems will always have some amount of triangle wave in the available heap measurement, but the more the GC runs the lower the ripple will be.

[quote]The background image is quite big - 3200x2500 px
[/quote]
Thats 32MB :o. The size of the maximum chung you can get varies, but 32 MB is probably to much. You’ll have to brake the image up.

Okay, so a few notes:

(1) Forget System.gc() except for very special cases. All calling gc() does is tell the Vm that you are willing to give up your thread of control to the garbage collector. What it actually does is highly VM dependent. (In Hotspot it causes an immediate full GC, which you generally DON’T want because its a gauranteed singificant pause, something Hotspot normally does its best to avoid.)

(2) Indeed a Vm is required to do whatever it can to free memory before throwing an out of memory error, so your problem ISN’T gc. As others have poinetd otu its likely whatw e call an “object leak” in our book-- forgotten references still hanging onto your data.

(3) To find object leaks USE A PROFILER!!!

(4) To find object leaks USE A PROFILER!!! (Repetition on purpose.)

(5) To learn more about Java and profilers, see our book, the entire contents of which is online at http://java.sun.com/docs/books/performance

On the sawtooth. Thats absolutely typical unless you are carefully preventing object creation. if you are creating a lot of temporary objects on the fly in your game they will build to some magic point where the VM decides some gc (may not necc be full) is required, at which point it will drop.

If you arent getting nasty gc pauses that hurt your game-play, I woudl just say “thank you VM” and not worry about it. If you ARE getting pauses then you need to either tune the gc behavior some (there are a whole bunch of -XX flags for this in Hotspot) or eliminate the object creation.

Alright… I’m starting to get the hang of how it should be done.

I wonder this though:

Tom said:

as a response to my 3200x2500 px bg image and I’d really like to now HOW it becomes that big… In my world (of illusions?) I’d like to calculate an image size as the nbr of px width times height and that would give me 3200 * 2500 = 8750000 = 8.75MB? This based on my assuming that the images are stored as int []?

Obviously, tom is correct since my JProfiler tells me that I’ve got 30MB+ stored in int [] but I really don’t understand why / how? How are images represented in Java?

[quote]I’d really like to now HOW it becomes that big… In my world (of illusions?) I’d like to calculate an image size as the nbr of px width times height and that would give me 3200 * 2500 = 8750000 = 8.75MB? This based on my assuming that the images are stored as int []?
[/quote]
Assuming each pixel is packed into an int (RGBA8) then thats 3200 * 2500 * 4 bytes, which is ~31MB. Or it may be just RGB in which case its ~23MB. But even then you’re likely to have each pixel packed to be 32 bits wide anyway, so it could be the same usage as RGBA8.

… and I’m supposed to have an engineering degree… :-[

Kind 'a forgot that an int consists of 4 bytes… Opps.

Thanx for not throwing that at me as hard as I deserved :wink: