【发布时间】:2019-10-02 16:00:59
【问题描述】:
我写了一个代码来检查ImageIO.read是否会占用大量内存,然后导致高内存使用。(之前有一个生产问题)
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 大约 4.3MB(我猜可能是额外的内存 4.3 * 20 *(3 或 4)不包括 JVM)。
我使用jemalloc 来跟踪内存分配。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
htop 中的 RSS 大约 160M,我打印了 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)
已提交大约 109MB。
如果我在代码中什么都不做,就打印一些东西。
它将 malloc 200MB。(在注释掉 ImageIO 和相同选项之前使用代码)。
因此,阅读 4.3MB jpeg 20 次几乎需要 800MB。
(Ps:只需使用 Files.readAllBytes 读取 jpeg 文件只需 malloc 256MB 使用相同的选项)
这正常吗?以及如何使用ImageIO优化内存?
【问题讨论】:
-
JPEG是压缩的(其实就是的压缩方式),Java肯定是不压缩保存图片的,也就是每个像素...所以像素计数很重要,而不是磁盘空间来确定使用了多少内存 - 相关:stackoverflow.com/q/12489009/85421
-
jeprof - 显示 77.9% 的内存(约 770 mb)用于解码图像像素映射。 IE。 ARGB 像素颜色分量数组(每个像素 4 个字节),它是 int 类型的数组。
-
@CarlosHeuberger thx~
-
@VictorGubin 因为堆没有使用额外的内存(大小固定)。所以本机库使用了大量内存?反正thx~
-
据我所知,从java 1.4开始,BufferedImage默认光栅可以直接在video-ram中为图像像素图分配内存。在句柄模式下,它应该是对默认系统 VirtualAlloc/mmap 等的调用。
标签: java