As I have found out every call to getResourceAsStream() wastes as much system memory as was the size of the resource. This piece of memory is not released until the whole MIDlet stops.
This bug exists on the 7650 (4.45) and 3560 (2.50) but not on the 7650 (3.xx). So it seems that it has been introduced into the codebase only recently.
The problem also causes a call to createImage(String name) to lose as much memory as was the size of the .PNG. (obviously createImage() internally just calls getResourceAsStream()).
I could not find a workaround for this problem. My application needs to load/release images quite often and also runs a very long time. So with this bug still present the programm eventually will run out of memory.
Possibly the only thing to do is to never release binary data of the .PNG and create the actual image from this data on demand.
The drawback of the solution is of course that I finally have all .PNG in memory _twice_ (once because of the leak and the second time because I may not release the data since every subsequent read would again leak memory).
As long as this bug is not fixed, big long-running applications (in the style of "legend of zelda") are nearly impossible.
we ran into similar problems with our latest game (XGRA for Acclaim), which uses texturemapping, zooming sprites, and scrolling backgrounds (complete screen) - we use a whole shitload of graphics which we need to swap in and out.
Whilst the game performed brilliantly on the Series 40, migration to 60 was a big pain - but finally we've worked out a very clean and good solution to avoid all those out-of-memory situations.
I assume you won't get any help from the system engineers on this very topic - but we can probably do something.
If you are interested, let me know about how to get in touch.
Ouh, I think this is a huge memory. I had about 124 kB sounds an another 80 k images, all stored in static ByteArrays. Memory was fine. So writing an image store doesn't seem to be a problem.
Besides you can write Runtime.getRuntime().freeMemory() to get what you are asking for (don't ask the emulator). So you may ask for the available memory right after starting the app in order to make sure the app will not crash in the middle of the game.
Hi all, I heard from mr Albech concerning my questions... I explained him I read the post and asked for additional information. I still had no reply from him, though I asked him if he could share bits of code or even the general idea behind the workaround in the forum itself.
I am waiting just as you.
I thought I was out of problems with Image.createImage and OutOfMemory as I don't try to get the memory used back but keep the handle same image objects all the time.
But I have a KERN-EXEC 3 error now ... I use a lot of big binary files for the game. But when I try to reload the same level few times, I finally get this error.
If someone found a work around, please tell us.
I tried to only open the file once and keep it's handle for reuse but I can't reset the cursor position in the file.
Then I tried to read the file only once and when it's needed another time, use a byte array that I saved containing it but I just run out of memory now.
The solution I came to was similar to your own, with one important difference. I broke down my original huge data file(mine were 8-bit-text) into many smaller ones.
I did this because whenever I tried to create any kind of reader on the stream, the reader seemed to create itself a large buffer that was the size of the file. This meant peak memory usage was 2n... (blowing out the heap)
By cutting down each file into a small chunks you can still do a
byte data = new byte;
Then read in each chunk of say 10K.
I used to load binay files containing images in ARGB_4444 format by using getResourceAsStream (because I knew that Image.createImage doesn't release the memory on series 60). As the images were usually full screen (176x208) or more, I got kern-error pretty quickly.
I've replaced these images by png that I load by using Image.createImage. I have a class which contains all these images and which is instanciated once, when I start the application. Then all classes that need images, get them through this class. I also use small binary files and open them only once at the begining.
It's not really nice as it's sometimes wasting memory but at least i got rid of that kern-error.
I'm using a very similar workaround for a tile based game I am developing. Again, it's not right but it's OK.
Firstly I have a ResourceLibrary class that is essentially a thin wrapper around Hashtable containing images. When a level loads, I check to see if the source images are in the ResourceLibrary and if not I load them. The images are then available from the library if the level is loaded again. By loading on demand and then 'caching' you don't get the delay at startup associated with getting all the images for all the levels up front.
Secondly, because I am splitting some of the images into individual tiles for the scrolling background, I created an image pool. This is analogous to connection pooling in database applications except that I'm not destroying the images after a certain period of time if they are unused. By this second method the image objects in the pool are not destroyed when the next level loads but are written over - it's a bit like a software Etch-A-Sketch.
Using the above methods I was able to sustantially reduce the memory leak problems I was experiencing.