伙计们,我想用Java创建一个尺寸为20000 x 20000或更大的巨大BufferedImage,但Java抛出了以下异常:
java.lang.OutOfMemoryError:java堆空间
如何避免此异常?Java有可能创建如此大的图像吗?
虽然增加堆大小当然更容易,但我创建了一个特殊的DataBuffer
实现,它允许您将BufferedImage
的内存保留在堆外。它使用NIO内存映射文件缓冲区,工作方式类似于虚拟内存。它比使用普通的BufferedImage
慢得多,但可能有助于加载和处理过大的图像。
请参阅MappedImageFactory.java和MappedFileBuffer.java了解实现(BSD许可)。
用法简单如下:
int w = 20000;
int h = 20000;
BufferedImage image = MappedImageFactory
.createCompatibleMappedImage(w, h, BufferedImage.TYPE_INT_ARGB);
我已经成功地使用它来加载和显示一个只有32MB堆的2GB图像。
请确保,要使用64位java和64位系统:
在大多数现代32位Windows系统上,最大堆大小将在1.4G到1.6G之间。在32位Solaris内核上,地址空间限制为2G。在运行32位虚拟机的64位操作系统上,最大堆大小可能更高,在许多Solaris系统上接近4G
然后添加一些堆:
尝试-Xmx2048m或-Xmx2g
到您的"java"调用(JVM参数)
因为如果你使用RGB或ARGB类型的图像,那么每个像素都是int
类型
20 000 x 20 000=40 000 000*4(int有4个字节)=约400 MB*4=约1600 MB
假设您希望拥有更大的映像,并且您的应用程序需要一些空间,以及JVM,您可能希望拥有更多或更少的堆,那么您需要做出决定。
如果你有4GB的RAM,正如你在问题下面的一些评论中所说,这会限制你可以创建的图像的大小,你需要从4GB中减去系统、其他应用程序和JVM的RAM数量,那么你就不能创建比你剩下的内存更大的图像。
您可以创建一个black&白色图像(1位/像素)如下:
IndexColorModel colorModel = new IndexColorModel(
1, // bits per pixel
2, // number of colors
new byte[]{0, (byte) 0xff}, // red values
new byte[]{0, (byte) 0xff}, // green values
new byte[]{0, (byte) 0xff}); // blue values
BufferedImage image = new BufferedImage(20000, 20000,
BufferedImage.TYPE_BYTE_BINARY, colorModel);
需要20000*20000位=50 MB。