【发布时间】:2017-05-22 06:51:29
【问题描述】:
我有一个扩展 JComponent 的 ImageViewComponent。该组件被添加到 JPanel 中,该 JPanel 被添加到 JFrame。从另一个类中,我定期从另一个类更新 ImageViewComponent 的 int[] image 字段。
问题是这个过程会占用大量内存。它甚至消耗了如此多的内存(根据 JProfiler,几秒钟后 +/- 130 MB,最终超过 1GB),以至于整个程序在垃圾收集期间经历了“滞后峰值”(程序中的滞后同时发生内存被清除)。
这是ImageViewComponent的代码:
public class ImageViewComponent extends JComponent {
private int image_width, image_height, updateInterval, updateCounter;
private int[] imageArray;
private BufferedImage currentDisplayedImage;
private Image scaledDisplayedImage;
/**
* @param width The width of this component
* @param height The height of this component
* @param ui The higher, the less frequent the image will be updated
*/
public ImageViewComponent(int width, int height, int ui) {
setPreferredSize(new Dimension(width, height));
this.updateInterval = ui;
this.updateCounter = 0;
this.currentDisplayedImage = null;
this.scaledDisplayedImage = null;
}
public void setImage(int[] image, int width, int height) {
this.imageArray = image;
this.image_width = width;
this.image_height = height;
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (image_width == 0 || image_height == 0)
return;
else if (updateCounter != updateInterval && currentDisplayedImage != null) {
g.drawImage(scaledDisplayedImage, 0, 0, this);
updateCounter++;
return;
}
this.currentDisplayedImage = new BufferedImage(image_width, image_height, BufferedImage.TYPE_INT_RGB);
this.currentDisplayedImage.setRGB(0, 0, image_width, image_height, this.imageArray, 0, image_width);
this.scaledDisplayedImage = this.currentDisplayedImage.getScaledInstance(this.getPreferredSize().width,
this.getPreferredSize().height, BufferedImage.SCALE_DEFAULT);
g.drawImage(scaledDisplayedImage, 0, 0, this);
// reset update counter
updateCounter = 0;
}
}
JProfiler 声明其活动内存的 70% 的程序在此类中分配,50% 在 Graphics.drawImage 中,而 20% 在 BufferedImage 初始化中。
我尝试通过将行 this.currentDisplayedImage = new BufferedImage(image_width, image_height, BufferedImage.TYPE_INT_RGB) 放入“setImage”中来修复它,并让它只用一个布尔标志设置一次,但这会使绘制的图像偶尔在短时间内完全变黑,也不它是否解决了内存问题。
我也尝试了this 的建议,也没有用。
如何解决这个内存问题?
【问题讨论】:
-
避免在
paintComponent方法中完成所有工作。使用ComponentListener来检测组件大小的变化,然后更新缩放的实例。我还将仅在setImage方法中创建新的BufferedImage,调用repaint来触发绘画通道 -
@MadProgrammer 组件本身的大小不变,图像大小也不变。我重新调整它是因为
int[] image的尺寸比组件大。setImage方法经常被调用,每次使用完全不同的图像(它从以大约 60fps 运行的模拟器获取图像)。我将在setImage中创建BufferedImage,并使用布尔标志只运行一次,就像我之前尝试的那样。还有什么我应该考虑的吗? -
提供一个可运行的例子
-
我还要验证它是导致内存泄漏的组件,而不是生成
int[]
标签: java image swing memory graphics