Я занимаюсь разработкой приложения на базе Java. Здесь моя работа - поместить изображение в JLabel
. Если я загружаю более 60 изображений в метки, тогда java показывает «Ошибка пространства кучи» (см. Ниже).Ошибка буфера памяти BufferdImage
Я не хочу увеличивать размер пространства кучи 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)
возможно добавить полное сообщение об ошибке в дополнение к коду – Chris
java.lang.OutOfMemoryError: Java пространство кучи \t в java.awt.image.DataBufferByte. (DataBufferByte.java:92) \t на java.awt.image.ComponentSampleModel.createDataBuffer (ComponentSampleModel.java:415) \t на java.awt.image.Raster.createWritableRaster (Raster.java:944) \t в javax .imageio.ImageTypeSpecifier.createBufferedImage (ImageTypeSpecifier.java:1073) \t на javax.imageio.ImageReader.getDestination (ImageReader.java:2896) \t в com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal (JPEGImageReader.java : 998) \t at com.sun.imageio.plugins.jpeg.JPEGImageReader.read (JPEGImageReader.java:966) –
Ваш 'JLabel' с' ImageIcon' будет удерживать ссылку 'img', даже если вы делаете null e - локально. Это потребует данных изображения снова для каждой перерисовки. 'flush()' in the BufferedImage' не освобождает кучную память, поэтому это не хорошо. Также JVM должен сделать GC, прежде чем сдаваться и бросать OOME, поэтому нет необходимости запрашивать явный GC. Мне кажется, вам нужно либо избавиться от некоторых 'JLabel' с 'Icon', либо просто увеличить размер кучи JVM. – haraldK