【发布时间】:2014-09-25 10:05:37
【问题描述】:
我正在开发一个基于 Java 桌面的应用程序。在这里,我的工作是将图像放入JLabel。如果我将超过 60 个图像加载到标签中,那么 java 会显示“堆空间错误”(见下文。)
我不想增加 JDK 的堆空间大小。我只想在JLabel 中显示图像后释放内存。我将flush() 用于BufferedImage:它不会清除内存。
这是我的代码
public static void setImageInLabelFromBufferedImage(JLabel label, int commonWidth, int maxImageHeight, BufferedImage img) {
try {
if (img.getWidth() < commonWidth && img.getHeight() < maxImageHeight) {
**img = Scalr.resize(img, Scalr.Mode.AUTOMATIC, img.getWidth(), img.getHeight(), Scalr.OP_ANTIALIAS);**
} else {
if (img.getWidth() > img.getHeight()) {
if (img.getWidth() > commonWidth) {
img = Scalr.resize(img, Scalr.Mode.FIT_TO_WIDTH, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
}
} else if (img.getHeight() > img.getWidth()) {
if (img.getHeight() > maxImageHeight) {
img = Scalr.resize(img, Scalr.Mode.FIT_TO_HEIGHT, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
}
} else {
img = Scalr.resize(img, Scalr.Mode.FIT_EXACT, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
}
}
//BufferedImage resizedImage = Scalr.resize(img, Scalr.Mode.AUTOMATIC, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
label.setIcon(new ImageIcon(img));
label.revalidate();
img.flush();
img = null;
Runtime.getRuntime().gc();
} catch (Exception e) {
log.error("setImageInLabelFromBufferedImage==>" + e.getMessage());
}
堆栈跟踪:
java.lang.OutOfMemoryError: Java heap space at
java.awt.image.DataBufferByte.<init>(DataBufferByte.java:92) at
java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:415) at
java.awt.image.Raster.createWritableRaster(Raster.java:944) at
javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1073) at
javax.imageio.ImageReader.getDestination(ImageReader.java:2896) at
com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:998) at
com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:966)
【问题讨论】:
-
除了代码之外,还可以添加完整的错误信息
-
java.lang.OutOfMemoryError:java.awt.image.DataBufferByte 处的 Java 堆空间。
(DataBufferByte.java:92) 处 java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java :415) 在 java.awt.image.Raster.createWritableRaster(Raster.java:944) 在 javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1073) 在 javax.imageio.ImageReader.getDestination(ImageReader.java:2896)在 com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:998) 在 com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:966) -
您的
JLabel和ImageIcon将保留img引用,即使您在本地执行 null 引用。每次重绘都需要图像数据。flush()BufferedImage不会释放堆内存,所以不好。此外,JVM 应该在放弃并抛出 OOME 之前进行一次 GC,因此无需要求显式 GC。在我看来,您需要用Icons 摆脱一些JLabels,或者只是增加JVM 堆大小。 -
但我需要带有图标的 jlabel .. 有没有其他方法可以做到这一点?我将 JtextPane 与 html 内容一起使用。在这种情况下,问题是一样的。
标签: java out-of-memory heap-memory bufferedimage