I'm writing a photo library application just for practice. I'm trying to display all the jpegs in an album by displaying thumbnails of them as ImageIcons in JLabels on a JFrame.
To get the images I use ImageIO.read(File) into a BufferedImage. Then using Image.getScaledInstance I pass the resized image to a new ImageIcon which is added to the JLabel. This all happens in a final class ThumbDisplay, method showPic which returns the JLabel.
I call ThumbDisplay.showPic(File) in a loop, and it can read about 5 files before throwing an OutOfMemoryError. I have been able to successfully display no more than 4 images. Most of my images were taken on my digital camera and are around 2560X1920.
I read a bit about the java heap space and I understand how 5 BufferedImages of that size open at once can easily eat up memory. But the code looks to me that any instantiated BufferedImages would be GC'd as soon as the showPic method returned the JLabel. JHAT proved otherwise and there were still 5 instances of BufferedImage when I got the OutOfMemoryError.
So, the following is my example code block and the StackTrace. No extra stuff required. Just throw about 10 extra large jpegs in whatever path you choose to put in 'File directory' on line 9, compile and run. I'd really appreciate some help on this. I've searched countless message boards for that error and found many similar topics but ZERO answers. Can someone tell me why these aren't getting GC'd?
code:
1. import javax.swing.*;
2. import java.awt.image.*;
3. import javax.imageio.*;
4. import java.awt.*;
5. import java.io.*;
6.
7. public class ThumbTest{
8. public static void main(String args[]){
9. File directory = new File("c:\\pictemp\\");
10. File[] files = directory.listFiles();
11. JFrame jf = new JFrame();
12. jf.setSize(1000,1000);
13. jf.setLayout(new GridLayout(10,10,15,15));
14. for(File file : files)
15. jf.add(ThumbDisplay.showPic(file));
16.
17. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
18. jf.setVisible(true);
19.
20.
21. }
22. }
23.
24. final class ThumbDisplay{
25.
26. public static JLabel showPic(File f){
27. BufferedImage img = null;
28. try{
29. img = ImageIO.read(f);
30. }catch (IOException e){
31. e.printStackTrace();
32. }
33. if(img != null){
34. float ratio = 100 / (float) img.getHeight();
35. int w = Math.round((float)img.getWidth() * ratio);
36. int h = Math.round((float)img.getHeight() * ratio);
37. return new JLabel(new ImageIcon(img.getScaledInstance(w,h,Image.SCALE_DEFAULT)));
38. } else
39. return new JLabel("no image");
40. }
41. }
exception:
1. D:\java\Projects\PhotoLibrary>java ThumbTest
2. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
3. at java.awt.image.DataBufferByte.<init>(Unknown Source)
4. at java.awt.image.ComponentSampleModel.createDataBuffer(Unknown Source)
5. at java.awt.image.Raster.createWritableRaster(Unknown Source)
6. at javax.imageio.ImageTypeSpecifier.createBufferedImage(Unknown Source)
7. at javax.imageio.ImageReader.getDestination(Unknown Source)
8. at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Sou
9. rce)
10. at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(Unknown Source)
11. at javax.imageio.ImageIO.read(Unknown Source)
12. at javax.imageio.ImageIO.read(Unknown Source)
13. at ThumbDisplay.showPic(ThumbTest.java:29)
14. at ThumbTest.main(ThumbTest.java:15)