0

I have a program that uses a lot of images. It loads alot of images from file, and stores them so they are only loaded once. It also creates multiple BufferedImages, about 400x400, there would be no more than 10 of these.

The images from file total around 6MB. Each BufferedImage should be approx 400x400x4=640KB.

Yet, the memory usage is 500MB!

Some of this will be for the rest of the program, but I'm pretty sure that the images are taking up most of the space.

Does anyone know what to do about this? Or an alternative to BufferedImage that uses less memory?

DanielGibbs
  • 9,910
  • 11
  • 76
  • 121
  • 3
    Sounds fishy, I would blame your code before I blame libraries, sorry. Care to paste some of it? What happens when you force the garbage collector to run? There must be some memory profilers for java available. http://www.google.com/#hl=en&expIds=17259,18168,26792,26885,27006&sugexp=ldymls&xhr=t&q=memory+profiler+java&cp=17&pf=p&sclient=psy&safe=off&aq=0&aqi=g4g-o1&aql=&oq=memory+profiler+j&gs_rfai=&pbx=1&fp=7c8f32f65b860aba – Hamish Grubijan Oct 06 '10 at 01:24
  • Agree with Hamish, it could be a bug in the code that loads and caches the images. Perhaps it's actually loading and caching images more than once each. – Andy White Oct 06 '10 at 01:26
  • Yea, initially I assumed it was a memory leak. But as soon as it starts, at the very most, 10 of the 400x400 BufferedImages are made. And it is 500MB at the start, it doesn't seem to grow much from there, its just a huge amount at the beginning. @Hamish We have tried forcing the garbage collector, but that doesn't do too much. I will look into the memory profiling tools when I get a chance. As for pasting the code, it would be rather impractical as it is actually rather spaghetti-ish. We are working on an adventure game for a group project for university and the code is a complete mess =s. – DanielGibbs Oct 06 '10 at 10:13
  • @DanieL, how do you know that it is images that are causing this problem? You could easily create a gigabyte of just data if you are not careful. Memory and CPU usage can explode exponentially if you are trying to do a TSP problem, for instance. You need to profile to figure out the actual bottleneck. – Hamish Grubijan Oct 06 '10 at 14:04
  • I've just had a play with jvisualvm, For some absurd reason I actually do have 206 BufferedImages. But the weird thing is, that for most of them, none of my objects have references to them. The only references to them in the profiler are biimage, referent, bImg, bufImg, and things like that. None of that is part of my code. Any idea why they still have references? Or how to get rid of them? – DanielGibbs Oct 06 '10 at 18:06
  • I have not used Java in years - just a random guess ... perhaps they are being handled natively (JNI). Maybe they are being stored in some sort of collection (such as hash table) by a key. It is possible, however, that the library you are using is total crap (I have not bothered to look). This is something that you need to do. if you are spinning your wheels this long, perhaps try another library. Start a minimal project which tests just images by themselves using two different libraries, and see whether one is much better than another. In the interest of time, just pick what works well enough – Hamish Grubijan Oct 07 '10 at 14:50
  • @DanieL, I do not know how much time you have been putting into this. Perhaps 4 other classes keep you busy. If you had been working at this 8 hours per day, then you are impeded and you need to try lots of different things. If you were paid $50/hr, and spent 8 hours to no avail - that is $400 down the drain for your employer. While money is probably not involved at a University project, you need to proactively approach this in an agile manner. If you picked a bad library - you need to detect that ASAP. Try stuff. Say, copy and reduce your project to the minimal bottleneck. Then show code here – Hamish Grubijan Oct 07 '10 at 14:55
  • Ugh... It was a problem in the code, well some of it at least. I managed to half the memory usage by putting a "static" in fron of one of the fields, where it always should have been... – DanielGibbs Oct 08 '10 at 09:00

2 Answers2

4

It sounds to me like your application (not the library) has a memory leak. In the first instance you should try to identify the leak using a standard Java memory profiler.

EDIT

Now you've identified that there are lots of BufferedImages hanging around, the next thing you need to do is figure out why they are still reachable. Take a heap dump, look at some instances and see how they are connected to a heap root; see http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/heapdump.html

When doing this kind of stuff, it is useful to look at the relevant parts of the Java source code using your favorite Java IDE.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    Start with VisualVM http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/profiler.html ... or look at the results of the Google search provided above in a comment. – Stephen C Oct 06 '10 at 02:23
  • Thanks! I didn't realise I had this on my machine the whole time... Well it looks like BufferedImages are the problem, I have 206 of them =O. But none of my objects have references to most of them! So they seem to stick around after I'm done with them... – DanielGibbs Oct 06 '10 at 10:55
  • I've had a look at the heap dump and the only references to them are biimage, referent, bImg, bufImg, and things like that. None of that is part of my code. Any idea how to get rid of them? – DanielGibbs Oct 06 '10 at 19:27
  • Examine the reference chains back to the heap roots. I'd be very surprised if at least one of the references in the chain is not being held in a class or instance variable of a non-JDK class. And even if that is the case, there's probably some JDK method that will break the chain at the root allowing everything to be GC'ed. – Stephen C Oct 06 '10 at 21:57
  • Just to make it clear, you just need to break the chains back to the GC roots ... somewhere ... and the objects become unreachable, and eligible for garbage collection. – Stephen C Oct 06 '10 at 23:49
1

Is your program a web application ? or you are developing a JRE-like application ? How do you load up your images ?

In a web-based application, I would use a CSS-Sprite image to solve my problem, because it cut off several HTTP requests and improve both bandwith usage and memory usage on load.

In a JRE application, there should be a way to use an image sprite in the same way, loading an offset of 400x400 of your image sprite to reduce usage of the BufferedImage object and improving performance.

LoganWolfer
  • 115
  • 1
  • 11
  • It is a normal JRE program. The images that are loaded from file use Toolkit.getDefaultToolkit().createImage(imageName). The BufferedImages are created using the standard BufferedImage constructor. Not quite sure what you mean about the image sprite, do you have an example? – DanielGibbs Oct 06 '10 at 10:16
  • You can check out for this website for the web-based version of a sprite technique : http://css-tricks.com/css-sprites/ I still haven't found any way to implement such a technique in a JRE-based program, maybe the lead of Stephen C could be helpful. – LoganWolfer Oct 06 '10 at 15:30