I wrote a code to check if ImageIO.read
would take much memory and then cause high memory usage.(there was a production issue before)
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageIOTest2 {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
BufferedImage image;
try {
image = ImageIO.read(new File("test.jpg"));
System.out.println(image);
Thread.sleep(100);
} catch (IOException) {
e.printStackTrace();
}
}
}
}
test.jpg is about 4.3MB (I guessed maybe extra memory 4.3 * 20 * (3 or 4) exclude JVM).
I use jemalloc
to track memory mallocation.
LD_PRELOAD=/usr/local/jemalloc/lib/libjemalloc.so MALLOC_CONF=prof:true,lg_prof_sample:17,lg_prof_interval:25,prof_prefix:/root/output/je java -Xmx64m -Xms64m -XX:NativeMemoryTracking=summary ImageIOTest2
The RSS in htop was about 160M and I printed the NMT:
Native Memory Tracking:
Total: reserved=1377MB, committed=109MB
- Java Heap (reserved=64MB, committed=64MB)
(mmap: reserved=64MB, committed=64MB)
- Class (reserved=1037MB, committed=10MB)
(classes #827)
(malloc=5MB #716)
(mmap: reserved=1032MB, committed=5MB)
- Thread (reserved=16MB, committed=16MB)
(thread #17)
(stack: reserved=16MB, committed=16MB)
- Code (reserved=244MB, committed=3MB)
(mmap: reserved=244MB, committed=2MB)
- GC (reserved=8MB, committed=8MB)
(malloc=6MB #118)
(mmap: reserved=2MB, committed=2MB)
- Internal (reserved=5MB, committed=5MB)
(malloc=5MB #2080)
- Symbol (reserved=2MB, committed=2MB)
(malloc=1MB #200)
(arena=1MB #1)
committed is about 109MB.
But the total memory from jeprof is 1055.7M:
If I do nothing in code just print something.
It will malloc 200MB.(Using the code before comment out ImageIO and same options).
So almost 800MB for reading a 4.3MB jpeg for 20 times.
(Ps:Just read the jpeg file using Files.readAllBytes just malloc 256MB using the same options)
Is this normal? And how to optimize memory using ImageIO
?