This week's book giveaway is in the Open Source forum.
We're giving away four copies of Programmers Guide to Apache Thrift and have Randy Abernethy on-line!
See this thread for details.
Win a copy of Programmers Guide to Apache Thrift this week in the Open Source forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Knute Snortum
  • Paul Clapham
  • Tim Cooke
Sheriffs:
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Bear Bibeault
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Ron McLeod
  • Piet Souris
  • Frits Walraven
Bartenders:
  • Ganesh Patekar
  • Tim Holloway
  • salvin francis

What is the best way to load/unload images on a swing application to avoid memory leak?  RSS feed

 
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi guys, please, I need help.
I'm facing a big memory leak problem handling images in a swing application.
The program I wrote is very complex and thousands of lines long, I will not post code here because it's not the point of what I'm asking.
What I am asking is: what is the best way to load/unload an image, for example in a simple JLabel, to avoid memory leak?
I read a lot of forums and tried a lot of solution but unfortunately none worked.
Could you be so kind to give me a hint of code that can load an image on a JLabel and then unload it and then free the memory allocated (forcing the garbage collector or making sure that is collectable)?
All the solutions I tried so far are not resolving the memory leak.
As I said, please don't ask me lines of code, just give me the right solution so I can implement it later.
The code I need should open a JLabel (on a JFrame or JDialog, it doesn't matter) with an image inside and then close it (dispose or whatever) in order to free the memory allocated so that calling it again and again and again won't cause any memory issue.
Thanks in advance for your help.
 
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please tell us what you have tried, so we don't suggest the same again. Please also give us lots of details, including size and number of images, heap size, and error messages. Also tell us how you are referencing images, particularly those no longer in use.

This isn't a “beginning” question, so I shall move you to another forum.
 
Luca Vanon
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the reply.
As I said the program I wrote is very long and complex, but that's not the point.
I don't want to know what I'm doing wrong (I will discover it myself later), I want to know what is the correct way to do it.
I tried so much things that I have a lot of difficulties to write a list.
Could you write a small program that simply open a JLabel inside a JFrame or a JDialog with an image and then dispose it so that no memory leaks occours?
I understood after many attempts that simply disposing the JDialog or JFrame cause infinite memory leaks.
Thanks for the support!
 
Luca Vanon
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is not the original code, just an example I made to get to the point:



This simply create a JFrame with 3 JButton opening 3 different JDialog each one has a label with a big image inside.

They are set to DISPOSE_ON_CLOSE so what I expect is:

1) I press the first button: the JDialog opens and a big amount of memory is allocated.
2) I close the JDialog with the X and it is disposed (so set to be collectable from the garbage collector or something like that when needed)
3) I press the second button: the second JDialog should open (because the first one is no longer in use and it's resources should be collected and free)

Unfortunately that's not the case...
After pressing the second button I receive a "java.lang.OutOfMemoryError: Java heap space"

What should I do to free the memory allocated in the first JDialog?
Why after his disposal it is not collected?
Thanks for your help!
 
Bartender
Posts: 5817
56
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Creating a new ImageIcon every time a button is pressed is not a good idea because image loading typically takes a bit of time (depending on the image size).This will slow down the responsiveness of your GUI. It would be better to load all the images at the start of the program and then use the references to those. IF your images are humongous this may not fix your problem but for three buttons this is normally not an issue.

How big are your images?
 
Luca Vanon
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, but that's not an answer to my question.
As I said this is just an example.
The real application has a lot of images, big images, but that's not the point.
The point is: how can I free the memory allocated?
Why disposing the element doesn't free the memory?
I don't want to avoid creating new images, new labels, new dialogs, new frames, I need them couse my program has to be able to handle multiple sessions of the same frames/dialogs etc. simultaniously.
But, again, that's not the point.
I want to understand why disposing an element is not deallocating the memory and how can I do that hundreds of times, if necessary.
Thanks.
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does this smaller GUI show the same problems? Does it give any line numbers in the stack trace? How many images are you loading? How much heap space have you got?
Have you got any profiling tools? I can't remember what it is called, but there is often one such tool packaged with the JVM. Maybe it's jconsole. What sort of memory consumption does it show? You can even get very basic memory consumption figures with some of the methods of Runtime.
Let's imagine you have a 3072×2048px image. that will occupy up to 24MiB. Even my little 11½″ has 4GB of RAM and the maximum heap defaults to 25% of that, so I am surprised that you can't get your pictures into that space. I shall come back to your problem and try something later on.
 
Luca Vanon
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't want to be misunderstood: I really appreciate your help, but again, that's not the point.
I don't want to use less memory, make the heap size bigger or other solutions that will only procastinate the problem.
My program must be able to open and close multiple session, unlimited times, so even if the images allocate less memory sooner or later the free memory will finish.
My question is still ununswered: what is the correct way to allocare and that deallocate the memory for that image?
Why dispose doesn't work?
Let's say I'm doing a program that opens an image, let you write something on it and then save.
Then open a new one, close it, and again, multiple times, more than one at a time...
Why closing the windows doesn't deallocate the memory used to render the image?
 
Rancher
Posts: 3040
22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe add a WindowListener to the dialog and in the windowClosing()  event you can invoke code like:



I have never worried about garbage collection as it tends to do a good job, but I believe one way to give a hint to garbage collection is to set the variable to null to indicate it is not needed anymore.

Or I don't know if you can get the Window from the WindowListener and just set the window to null?
 
Campbell Ritchie
Marshal
Posts: 64471
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried your app with jconsole and a photo of mine; it showed about 65.9MB memory used, out of a potential maximum of 1GB. There were no exceptions thrown. Not even when I opened the same photo on three dialogue windows. Nor when I pressed the same button repeatedly without closing the dialogues.
Please supply more details, as I said in my first post.
Suggest:
  • 1: Start JConsole with the jconsole & instruction. Don't connect to any processes: click cancel. The & might not work on Windows®: don't know. I got JConsole to work on a separate terminal, so you may be able to use two command lines.
  • 2: Start Test with java Test.
  • 3: Connect from JConsole with Connection→New Connection→Local→“Test”→Connect. If it complains about not using SSL, click “Insecure connection”. What is going to go wrong on your own computer?
  • 4: Watch the memory use.
  • I think we need to see a program crash with an out of memory error in order to be able to help.
     
    Campbell Ritchie
    Marshal
    Posts: 64471
    225
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Rob Camick wrote:. . . one way to give a hint to garbage collection is to set the variable to null . . .

    I thought that wouldn't be necessary because the images go out of scope at the end of the actionPerformed() method. As OP said, the images are eligible for GC as soon as the dialogues are closed. I am at a loss to understand why he is running out of memory.
     
    Carey Brown
    Bartender
    Posts: 5817
    56
    Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You want an answer but you haven't given us enough info to go on. Does that last piece of code with three buttons also throw an OOM exception? If so, what steps do you take interacting with the GUI? Press '1', press 'x', press '2'? Can you provide links to the images you are using or similar ones that also fail in the same way. If you can't replicate the error in your example can you supply a simple piece of code that we could try to reproduce the error? A stack trace is imperative.

    OOM errors can happen with infinite loops or recursion or adding a reference to a collection that never lets go of it. None of these appear in your code sample. Perhaps a corrupted image?
     
    Luca Vanon
    Greenhorn
    Posts: 29
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi guys, thanks to all for the answers, I really appreciate that.

    Rob Camick, I will give a try to your code tomorrow when I'll go back to my office, thanks very much.

    Campbell Ritchie, you said you tried that code with your photo and used about 66Mb.
    I didn't check with jconsole but windows task manager is enough for me to see the increasing usage of memory.
    So, 66Mb is not much, nut you didn't tell us if that memory is deallocated after the window is closed and that's the issue.
    Let's say I open and close a window with a 66Mb picture 20 times, not the same picture and not the same window.
    20 different windows with 20 different images.
    If the memory is not deallocated each time sooner or later you will get an out of memory error.
    For me the thing is faster because I use bigger images that increase like 200/300Mb every time they are loaded, and I have not only 3 windows but plenty of them.
    That's said, this is not the point.
    The fact that you didn't have errors with a few images of 66Mb is not telling me if the memory is still increasing or not (in mine the answer is yes, I never had a memory decrease, only increase).

    As I said, the point is: why the memory is not deallocated after disposing the window?

    Carey Brown, I'm sorry if I didn't give you more information, but my original question was more "theorical"...
    What is the correct way to dispose a window (JFrame, JDialog or even a single JLabel) in order to avoid memory leak?
    Speaking of practical stuff, the piece of code with 3 buttons throw an exception, just try with much bigger images, something big enough to raise the memory allocation to 400/500Mb.
    You don't need to replicate the error, just take a look at the task manager and you will see that the memory allocation keep on growing and never decrease after the windows are closed.
    No corrupted images, just take very big ones, but, again, that's not the point. With smaller images the thing will happen again with more iterations.
    In my opinion I'm doing something wrong that didn't deallocate the memory when I close the windows.
    Please, answer me a question: is the memory decreasing when you close the windows? If not something is wrong...

     
    Campbell Ritchie
    Marshal
    Posts: 64471
    225
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Luca Vanon wrote:. . . bigger images that increase like 200/300Mb every time they are loaded . . .

    So how large are these images on disc? 300MB (not Mb) corresponds to 75Mpx, which is about 10000×7500px, or more. Can you get a camera that will take photos with the resolution?

    . . . I'm sorry if I didn't give you more information, but my original question was more "theorical"... . . .

    No, I didn't see the memory decrease, but there is no need for GC to occur when 94% of available memory is still vacant. Until we can see memory use not decrease when it is all occupied, we can't help.
     
    Luca Vanon
    Greenhorn
    Posts: 29
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    As before, the dimension of the images is not the point.
    You don't need a camera to generate a picture, you can do it with photoshop, 600dpi, big as a 2 meters poster or, it can be a different source as a SVG file with thousands of lines and curves rendered as an image, that's not the point.
    I can tell you that with bigger images the effect is more evident and at the end throws an error, but the basic is the same: the memory is never released and always increase.
    I still believe something is missing that prevent the garbage collector to set the window collectable.
    That's the answer I'm searching for...
     
    Rancher
    Posts: 427
    6
    Fedora IntelliJ IDE Spring
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Why do you remake the same thing every time even the it's only the image that is changing?
     
    Al Hobbs
    Rancher
    Posts: 427
    6
    Fedora IntelliJ IDE Spring
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    SO

    This link mentions freeing the resources of the image.  If you don't plan on using that image again you need to 'dispose' it.  ImageIcon has an Image object in there that isn't going away.  If you have memory leak than that's probably it, also probably remaking dialog boxes over an over again.  
     
    Master Rancher
    Posts: 4072
    47
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Luca Vanon wrote:...just take a look at the task manager and you will see that the memory allocation keep on growing and never decrease after the windows are closed.



    Al seems to have found the issue, but I just wanted to point out that dispose() doesn't force a garbage collection, so will not result in freeing up any heap straight away.
    More importantly, garbage collection does not mean that the JVM hands any memory back to the OS, so the task Manager is not representative of the amount of heap actually being used by your app.
     
    Luca Vanon
    Greenhorn
    Posts: 29
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks guys, Al Hobbs found a good solution with the flush().
    This seems to work with "simple" images, I did a few iterations and it seems that the memory exception is thrown only when the memory is actually not enough (that happens when you open more windows at the same time), but as soon as you close the windows when you re-open a window the image is loaded, this was not happening before and means that the resources are actually free again.

    Thanks a lot, but now I have a new problem...
    I don't know if I have to open a new discussion or we could go on here (I kindly ask the moderators if I have to move the discussion)...

    The problem now is with the SVG images.
    To render the SVG images I use an SVGPanel from the Salamander SVG library.
    A very big memory leak is here because I don't know how to dispose the SVGPanel (it doesn't come with a .dispose method).
    I'm searching for a solution in the Salamander repository but if you are familiar with this library and can help me it would be great.

    Dave Tolls, I know that looking at the task manager is not the same that using a console to monitor the memory usage, but it helped me to understand why the exported jar project was crashing on a PC with less memory than my workstation.

    Thanks again to all for your help!
     
    Al Hobbs
    Rancher
    Posts: 427
    6
    Fedora IntelliJ IDE Spring
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Never used svgsalamander so you need to put your code here and we can look at it.  Probably a similar thing is happening where the image resources are piling up in memory and you need to tell the program to free them up.
     
    Luca Vanon
    Greenhorn
    Posts: 29
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If you want I can post some code, but just the way I create the SVGPanel because I have no idea on how to remove/dispose the panel.
    I'm searching for info but everything I found tells you how to create it, not how to remove it.



    It works perfectly and display the SVG file just fine, but I don't know how to free the allocated memory that keeps on growing as before with the "simple" images.
    I'm searching for some methods or sub-classes of SVGPanel(), but with no luck for now.
     
    Luca Vanon
    Greenhorn
    Posts: 29
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Guys, I think I found the solution.
    If someone is searching for the same thing that's what I wrote in the code before closing the window:

    I don't know if it's the perfect solution but it seems to work.
    Thanks to all of you for your help!
     
    It is sorta covered in the JavaRanch Style Guide.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!