【发布时间】:2014-11-05 14:57:05
【问题描述】:
今天我有点在 Java 中摆弄图像打开/缩放/显示,并编写了一些代码来打开一个图像文件,随机缩放它并在短时间内显示它。
问题是:显示100-1000次后,我的“javaw.exe”使用的内存越来越大,甚至达到了1 GB的内存空间。
我不知道我的代码中的内存泄漏在哪里,因为唯一吃内存的东西是我的图片,并且只有 2 个(原始图像和正在缩放的图像,它总是分配给同一个变量(temp ) 所以“旧”的应该被 GC 挑选出来),也许你们可以看看它,它很简单。
1) 您从硬盘驱动器中选择图像
2) 随机缩放
3) 它会显示一小段时间然后消失
4) 转到 2)
为了缩放图像,我使用了这个库:http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.imgscalr.Scalr;
public static void main(String[] args) throws IOException, InterruptedException {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
BufferedImage originalImage = ImageIO.read(chooser.getSelectedFile());
BufferedImage temp;
while(true){
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
Thread.sleep(1000);
temp = Scalr.resize(originalImage,Scalr.Mode.FIT_EXACT, width, height);
showImage(temp, 800);
}
}
static void showImage(BufferedImage v,long length) throws InterruptedException {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(v)));
frame.setSize(v.getWidth(), v.getHeight());
frame.setVisible(true);
Thread.sleep(length);
frame.setVisible(false);
}
这是我第一次在这里发帖,如果我不清楚,请提出问题
提前致谢!
编辑:我监控了 javaw.exe 需要的内存
显示1张图片:75M 100张显示:330M 1000张图片显示:2,4G
编辑 2:
我现在已经采纳了您的有用建议,但我的内存量仍在增长,我的图像不再显示。JFrames 是空的。
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.imgscalr.Scalr;
public class App {
public static void main(String[] args) throws IOException, InterruptedException {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
BufferedImage originalImage = ImageIO.read(chooser.getSelectedFile());
BufferedImage temp;
JFrame frame = new JFrame();
while(true){
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
Thread.sleep(1000);
temp = Scalr.resize(originalImage,Scalr.Mode.FIT_EXACT, width, height);
showImage(temp, 500, frame);
}
}
static void showImage(BufferedImage v,long length, JFrame frame) throws InterruptedException {
SwingUtilities.invokeLater(
() -> {
frame.removeAll();
frame.revalidate();
frame.repaint();
frame.add(new JLabel(new ImageIcon(v)));
frame.setSize(v.getWidth(), v.getHeight());
frame.setVisible(true);
try {
Thread.sleep(length);
} catch (Exception e) {}
frame.setVisible(false);
frame.dispose();
});
}
}
也许我把你的建议放在了我的代码中的错误位置。
【问题讨论】:
-
你给 Java 多少内存?它最终会耗尽内存,还是最终会启动垃圾收集?
-
您在循环中创建新框架,但从不关闭它们(您只是使它们不可见),并且每个框架都有一个调整大小的图像。你应该得到内存泄漏。只要这些框架存在,垃圾收集就永远不会发生。另外,你在主线程上。这永远不会奏效,你最终会耗尽内存并使 VM 崩溃。
-
您可能需要修改 vm 配置文件并为其提供更多内存。
-
@hagubear 这个问题与VM内存无关。该代码只是隐藏 JFrames 和其中的图像。这是一个应用程序逻辑问题。没有任何东西会被垃圾收集。
-
啊,我什至没有看到 showImage() 方法。尝试调用 frame.dispose() 而不是 frame.setVisible(false)。这样一来,框架的资源就被释放了,而不仅仅是隐藏了。
标签: java image memory-leaks