BufferedImage not going to GC
I cannot seem to get a BufferedImage to dispose. Every time I run the code below, the BufferedImage stays in memory until the app is closed.
Code:
private void test() {
BufferedImage bi = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_RGB);
try {
bi = ImageIO.read(new File("res/large.png"));
//test.flush();
//test = null;
} catch (IOException ex) {
}
}
I tried flush, setting to null, and both. Nothing seems to work.
Re: BufferedImage not going to GC
How are you determining that the BufferedImage is in memory? As an aside, never let exceptions fall through - at the least print out the Exception message.
Re: BufferedImage not going to GC
Absolutely.
I have compared the difference in memory usage when executing the method, and not.
I even executed this, which produced even greater memory use:
Code:
private void test() {
BufferedImage bi = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_RGB);
try {
bi = ImageIO.read(new File("res/large1.png"));
bi = ImageIO.read(new File("res/large2.png"));
bi = ImageIO.read(new File("res/large3.png"));
bi = ImageIO.read(new File("res/large4.png"));
//test.flush();
//test = null;
} catch (IOException ex) {
}
}
I think I'm going to use this instead as it doesn't seem to have the same memory issue:
Code:
Image image = Toolkit.getDefaultToolkit().createImage("res/large.png");
Re: BufferedImage not going to GC
Quote:
I have compared the difference in memory usage when executing the method, and not.
How? How do you know the garbage collector is getting called? How do you evaluate the object is in memory? To be more explicit, I'd recommend an SSCCE showing the problem, and a full description as to how you are determining the memory usage.
Re: BufferedImage not going to GC
Quote:
Originally Posted by
doWhile
How? How do you know the garbage collector is getting called? How do you evaluate the object is in memory? To be more explicit, I'd recommend an SSCCE showing the problem, and a full description as to how you are determining the memory usage.
Code:
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Main extends JFrame
{
public Main() {
runTest();
}
private void runTest(){
System.out.println("Total memory (bytes) before loading images: " +
Runtime.getRuntime().totalMemory());
loadImagesImageIO();
System.out.println("Total memory (bytes) after loading images (ImageIO): " +
Runtime.getRuntime().totalMemory());
loadImagesToolkit();
System.out.println("Total memory (bytes) after loading images (Toolkit): " +
Runtime.getRuntime().totalMemory());
}
private void loadImagesImageIO(){
BufferedImage bi = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_RGB);
try {
bi = ImageIO.read(new File("res/large1.png"));
bi = ImageIO.read(new File("res/large2.png"));
bi = ImageIO.read(new File("res/large3.png"));
bi = ImageIO.read(new File("res/large4.png"));
//test.flush();
//test = null;
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
private void loadImagesToolkit(){
Image image = Toolkit.getDefaultToolkit().createImage("res/large1.png");
image = Toolkit.getDefaultToolkit().createImage("res/large2.png");
image = Toolkit.getDefaultToolkit().createImage("res/large3.png");
image = Toolkit.getDefaultToolkit().createImage("res/large4.png");
}
public static void main(String[] args)
{
Main main = new Main();
main.setVisible(true);
}
}
large1.png to large4.png are 2048x2048 PNGs.
Here's the output I'm getting:
Total memory (bytes) before loading images: 16252928
Total memory (bytes) after loading images (Toolkit): 16252928
Total memory (bytes) after loading images (ImageIO): 84516864
I changed the order where ImageIO was executed first, and I got:
Total memory (bytes) before loading images: 16252928
Total memory (bytes) after loading images (ImageIO): 84516864
Total memory (bytes) after loading images (Toolkit): 84516864
Monitoring my memory use with Windows Task Manager, my memory never eventually drops.
Re: BufferedImage not going to GC
So what? Why is this an issue? The GC is never guaranteed to collect marked objects and often doesn't unless the application runs low on memory? And your memory monitoring still does not identify what occupies what spot of memory.
Re: BufferedImage not going to GC
Quote:
The GC is never guaranteed to collect marked objects and often doesn't unless the application runs low on memory?
I don't know. As the forum suggests, I'm new to Java. :)
Okay, well thanks for your help.
Re: BufferedImage not going to GC
Second what Fubarable said. I'd recommend googling terms like 'java garbage collection' for a plethora of resources on garbage collection to give you an idea why you observe what you do, how you can monitor the memory usage of an application, and when you should worry about it.
Re: BufferedImage not going to GC
Quote:
Originally Posted by
doWhile
Second what Fubarable said. I'd recommend googling terms like 'java garbage collection' for a plethora of resources on garbage collection to give you an idea why you observe what you do, how you can monitor the memory usage of an application, and when you should worry about it.
Thanks. I'll look around.
Re: BufferedImage not going to GC
Re: BufferedImage not going to GC
Okay, so you guys were right. Hovercraft Full Of Eels @stackoverflow provided me this link:
Understanding Weak References | Java.net
Another helpful link I found after reading the one above, was this:
http://java.sun.com/docs/books/perfo...PAppGC.fm.html
Quote:
An object enters an unreachable state when no more strong references to it exist. When an object is unreachable, it is a candidate for collection. Note the wording: Just because an object is a candidate for collection doesn't mean it will be immediately collected. The JVM is free to delay collection until there is an immediate need for the memory being consumed by the object.
Which is what you guys said. I'm off to skip and lick my lollipop without worry of allocated memory creep.
Thank you all
Re: BufferedImage not going to GC
Also, you are using totalMemory, which is the amount of memory the OS is providing to the JVM, not the amount of memory used in the heap.
That would be totalMemory - freeMemory.
totalMemory rarely shrinks, and is not a garbage collection thing in any case. I'm not entirely sure what mechanism controls the reduction in totalMemory.
So even if the image was collected you would not actually see that using that method.