簡體   English   中英

Java BufferedImage 內存消耗

[英]Java BufferedImage memory consumption

我們的應用程序生成圖像。 BufferedImage消耗的內存產生內存不足異常:

java.lang.OutOfMemoryError:Java 堆空間

這發生在以下行:

BufferedImage result = new BufferedImage(2540, 2028, BufferedImage.TYPE_INT_ARGB);

在這條指令之前檢查空閑內存時,它顯示我有 108MB 空閑內存。 我用來檢查內存的方法是:

Runtime rt = Runtime.getRuntime();
rt.gc();
long maxMemory = rt.maxMemory();
long usedMemory = rt.totalMemory() - rt.freeMemory();
long freeMem = maxMemory - usedMemory;

我們不明白BufferedImage怎么會消耗超過 100MB 的內存。 它應該使用 2540 * 2028 * 4 字節,即 ~20 MB。

為什么在創建BufferedImage時消耗了這么多內存? 我們可以做些什么來減少這種情況?

在多線程環境中向 Runtime 詢問可用內存量並不是真正可靠的,因為在您測量之后內存可能會被另一個線程用完。 此外,您使用的是maxMemory - usedMemory ,這不是可用內存量,而是 VM認為它最多可以提供的內存量 - 可能是主機系統無法滿足對更多內存的請求,而 VM仍然相信它可以擴大堆。

也完全有可能您的 VM有 108 MB 可用空間,但一個塊中沒有 20MB 可用。 您嘗試創建的 BufferedImage 類型最終由 int[] 數組支持,該數組必須作為連續內存塊分配。 這意味着如果堆上沒有可用的連續 20MB 塊,無論有多少可用內存,您都會收到 OutOfMemoryError。 使用的垃圾收集器使情況更加復雜——每個 GC 都有不同的內存分配策略; 可以留出相當大的堆部分用於線程本地內存分配。

如果沒有任何關於堆總共有多大的信息,你正在使用哪個 GC(以及哪個 VM),有太多的變量無法指出罪魁禍首。


編輯:找出使用的 GC( Java 7 (JDK 7) 垃圾收集和 G1 上的文檔),並了解其特定的優缺點 - 特別是它在堆壓縮方面提供的功能以及它的代有多大默認。 那將是要使用的參數。 在 GC 消息開啟的情況下運行應用程序也可以提供對正在發生的事情的洞察。

考慮到您的堆只有 900MB 的大小,100MB 空閑意味着您已經非常接近限制了 -我的第一個解決方法是簡單地為 VM 分配一個更大的堆,比如說 2GB。 如果您需要節省內存,您唯一的選擇就是調整 GC 參數(可能選擇另一個 GC)——老實說,我沒有這方面的經驗。 不過,有很多關於 GC 調優主題的文章可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM