[英]Memory Leak(?) when displaying images in java
今天,我有點用Java來打開/縮放/顯示圖像,並寫了一些代碼來打開一個圖像文件,隨機縮放它並顯示一小段時間。
問題是:在顯示了100-1000次之后,我的“ javaw.exe”的已用內存越來越大,甚至達到1 GB的內存空間。
我不知道代碼中的內存泄漏在哪里,因為唯一的內存吃東西是我的照片,只有2張(原始圖像和正在縮放的圖像,總是分配給相同的變量(溫度),因此“較舊的”應該由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();
});
}
}
也許我把您的建議放在代碼的錯誤位置。
您可能要嘗試
originalImage.flush();
originalImage = null;
temp.flush();
temp = null;
但是無法保證您的圖片何時會被垃圾收集
除此之外,您還應該考慮清除並重新使用相同的JFrame。
removeAll();//or remove the previous JLabel
revalidate();
repaint();
同樣,顯示JFrame的正確方法是使用SwingUtilities invokeLater方法,以確保將此“作業”放置在事件調度線程(EDT)上。
// schedule this for the event dispatch thread (edt)
SwingUtilities.invokeLater(yourJFrame);
下面的代碼應做您想要的。 我使用計時器而不是Thread.sleep。 您正在捆綁EDT。 我也只是在容器中繪制圖像。 您可能應該改用JPanel(將其添加到JFrame並覆蓋其paintComponent方法)。 我還清理了一些方法。
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Graphics;
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 javax.swing.Timer;
import org.imgscalr.Scalr;
public class App extends JFrame implements ActionListener{
BufferedImage originalImage = null;
BufferedImage temp = null;
JFileChooser chooser = null;
public App(){
setVisible(true);
}
public static void main(String[] args) throws IOException, InterruptedException {
SwingUtilities.invokeLater(
() -> {
App app = new App();
Timer timer = new Timer(1000, app);
timer.start();
});
}
@Override
public void actionPerformed(ActionEvent ae){
if(null == chooser){
chooser = new JFileChooser();
chooser.showOpenDialog(this);
loadImage();
}
showImage();
repaint();
}
@Override
public void paint(Graphics g){
super.paint(g);
if(null == temp){
return;
}
g.drawImage(temp, 0, 0, null);
}
public void loadImage(){
try{
originalImage = ImageIO.read(chooser.getSelectedFile());
} catch(IOException ioe){
ioe.printStackTrace();
}
}
public void showImage() {
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
temp = Scalr.resize(originalImage,Scalr.Mode.BEST_FIT_BOTH, width, height);
setSize(width, height);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.