feexon / thumbnailator

Automatically exported from code.google.com/p/thumbnailator
Other
0 stars 0 forks source link

Memory Leak using Thumbnails.of(file).size(getWidth(),getHeight()).asBufferedImage(); #44

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.  Repeatedly generate thumbnails using code like: 
Thumbnails.of(file).size(getWidth(),getHeight()).asBufferedImage();

What is the expected output? What do you see instead?
If you watch the heap it grows very quickly, by several to tens of megabytes 
each time a thumbnail is generated.

What version of the product are you using? On what operating system? Which
version of Java (Sun/Oracle? OpenJDK?) ?
Netbeans 7.3 on OS X.

Please provide any additional information below.
Here is a simple program (testimage.jpg is a 2 MB image)
public static void main(String[] args) {
        File theFile = new File("testimage.jpg");
        BufferedImage currentThumbnail = null;

        for (int i = 0; i < 25; i++) {
            System.out.println(i+"\tCurrent Heap Size in MB: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024));
            try {
                currentThumbnail = Thumbnails.of(theFile).size(200, 200).asBufferedImage();
//                currentThumbnail = 
Thumbnailator.createThumbnail(theFile,200,200);
            } catch (Exception e) {
                System.out.println("Could not create thumbnail: " + e.toString());
            }
        }
    }

Below I show the output of the two calls to the library.  Thumbnails.of() 
continues to grow the heap and I run out of 512 MB heap after about 20 
iterations.  Thumbnailator.createThumbnail heap grows to about 125 MB max and 
then sits stable there. I feel like that's a pretty huge heap as well, but at 
least it settles down.

The Internet seems to suggest (various stackoverflow posts I have read) that 
the bufferedimages are probably being kept in a collection somewhere in the 
latter case and the references are never cleared so the images don't get 
garbage collected.  Since the Thumbnails.of approach is the one that handles 
EXIF rotation (my whole reason for using the library), this is dealbreaker for 
me right now. Thought you should know.

 Thumbnails.of output
-----------------------------------
0   Current Heap Size in MB: 1
1   Current Heap Size in MB: 55
2   Current Heap Size in MB: 76
3   Current Heap Size in MB: 122
4   Current Heap Size in MB: 152
5   Current Heap Size in MB: 142
6   Current Heap Size in MB: 194
7   Current Heap Size in MB: 230
8   Current Heap Size in MB: 240
9   Current Heap Size in MB: 240
10  Current Heap Size in MB: 286
11  Current Heap Size in MB: 286
12  Current Heap Size in MB: 332
13  Current Heap Size in MB: 378
14  Current Heap Size in MB: 355
15  Current Heap Size in MB: 400
16  Current Heap Size in MB: 400
17  Current Heap Size in MB: 423
18  Current Heap Size in MB: 446
19  Current Heap Size in MB: 458
20  Current Heap Size in MB: 481
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.awt.image.DataBufferByte.<init>(DataBufferByte.java:59)
    at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:397)
    at java.awt.image.Raster.createWritableRaster(Raster.java:938)
    at javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1056)
    at javax.imageio.ImageReader.getDestination(ImageReader.java:2879)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1046)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1014)
    at javax.imageio.ImageReader.read(ImageReader.java:923)
    at net.coobird.thumbnailator.tasks.io.FileImageSource.read(Unknown Source)
    at net.coobird.thumbnailator.tasks.SourceSinkThumbnailTask.read(Unknown Source)
    at net.coobird.thumbnailator.Thumbnailator.createThumbnail(Unknown Source)
    at net.coobird.thumbnailator.Thumbnails$Builder.asBufferedImage(Unknown Source)
    at thumbtest.ThumbTest.main(ThumbTest.java:29)

Thumbnailator.createThumbnail  output
-----------------------------------
0   Current Heap Size in MB: 1
1   Current Heap Size in MB: 63
2   Current Heap Size in MB: 61
3   Current Heap Size in MB: 121
4   Current Heap Size in MB: 136
5   Current Heap Size in MB: 120
6   Current Heap Size in MB: 133
7   Current Heap Size in MB: 117
8   Current Heap Size in MB: 124
9   Current Heap Size in MB: 113
10  Current Heap Size in MB: 120
11  Current Heap Size in MB: 110
12  Current Heap Size in MB: 117
13  Current Heap Size in MB: 124
14  Current Heap Size in MB: 113
15  Current Heap Size in MB: 120
16  Current Heap Size in MB: 110
17  Current Heap Size in MB: 116
18  Current Heap Size in MB: 123
19  Current Heap Size in MB: 113
20  Current Heap Size in MB: 120
21  Current Heap Size in MB: 110
22  Current Heap Size in MB: 116
23  Current Heap Size in MB: 123
24  Current Heap Size in MB: 113

Original issue reported on code.google.com by br...@fireplan.ca on 19 May 2013 at 6:26

GoogleCodeExporter commented 9 years ago
For what it's worth, the leak seems to be in the code that reads the file in.  
The following code does not exhibit the same problem:

                BufferedImage theImage=ImageIO.read(theFile);
                currentThumbnail=Thumbnails.of(theImage).size(200, 200).asBufferedImage();

Original comment by br...@fireplan.ca on 19 May 2013 at 7:01

GoogleCodeExporter commented 9 years ago
But of course if you do it the way I just commented (read it in yourself) you 
lose the EXIF rotation which is why I started in the first place.

Doh.

Original comment by br...@fireplan.ca on 19 May 2013 at 7:14

GoogleCodeExporter commented 9 years ago
I think I fixed it. Won't pretend to know exactly why. I knew something was not 
being disposed of properly, so I tried adding:
reader.dispose();

directly after:
iis.close();

Around line 155 of FileImageSource.java

Heap growth is now under control.

I feel like my morning was now spent productively. Hope to see this (or 
similar) patch soon :)

Original comment by br...@fireplan.ca on 19 May 2013 at 7:38

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Hi,

Thank you for taking the time and effort to report this issue.

There appears to be numerous cases of Thumbnailator encountering 
`OutOfMemoryError`s when using Java 7 Update 21.

I just want to get a verification of which version of Java was being used when 
you encountered this problem. (I'm going to guess it's Java 7 Update 21, also 
known as Java 1.7.0_21.) 

Thank you!

Original comment by coobird...@gmail.com on 20 May 2013 at 1:56

GoogleCodeExporter commented 9 years ago
No problem. So, I actually thought NetBeans bundled it's own JDK, but I may 
have been mistaken.  When I run the program and dump the appropriate system 
properties or just throw -version into the VM options, the answer is the same 
as from my OS X terminal window:
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06-451-11M4406)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01-451, mixed mode)

Original comment by br...@fireplan.ca on 20 May 2013 at 2:12

GoogleCodeExporter commented 9 years ago
Thank you for the prompt reply.

It's interesting to note that the problem occurred on Java 6 Update 45.

However, that is the most recent version of Java 6 (and apparently the last 
update for 6), and the `OutOfMemoryError`s on Java 7 was also the most recent 
release, so it seems like something in the most recent release of Java is 
causing the memory leak to be more apparent.

Issue 42 seems to be the same issue, so I will be merging this issue into that 
one.

Once again, I really appreciate all the information and the prompt reply! :)

P.S. I'll try to credit the people who have reported and contributed to this 
issue in the "Changes", so if you'd like to be acknowledged, please leave your 
name or nickname you'd like to acknowledged by in this issue.

Original comment by coobird...@gmail.com on 20 May 2013 at 2:22

GoogleCodeExporter commented 9 years ago
Please add Will Tran <will.tran@xtremelabs.com> to the acknowledgement list, 
thanks!

Original comment by will.t...@xtremelabs.com on 21 May 2013 at 5:51