[英]Outofmemory exception loading image files in Java
我在加载图像文件时遇到问题。 我已经测试了2种情况。 该问题仅在第一个中发生。 在这两种情况下,JDialog窗口都会显示缩小的图像。 300毫秒后,此窗口自动关闭(ImageDialog和CardPrinter的构造函数中有一个计时器;仅用于调试)。 在生产版本中,程序必须能够在JDialog中加载30-40个图像(一张一张)。 用户键入一些文本,然后单击按钮以显示下一张图像。 为了加载图像,我在两种情况下都使用ImageIO.read()。 或者,我使用了CMYKJPEGImage( http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/ ),但它也会产生异常。 在Main中,有一个myTimer,它用一个图像文件连续打开JDialog(应该通过设置变量pathtofiles用绝对路径调用listFilesRecurse())。
情况1)使用叠加布局管理器(Main.java,CardPrinter.java,IDCardLayout.java)在JDialog中加载图像。 为此,来自“ CardPrinter cp = null;”的行 到“ cp.dispose();” Main.java中的注释必须不加注释。 棘手的部分在addIDCard()@ CardPrinter中。 这将是建立的布局。 如果应该实现对话框窗口的内容,则会调用此paintComponent()@ IDCardLayout。 看起来,加载的图像不会被破坏,并且内存已满(可以在Window的Taskmanager中看到内存使用情况)。
情况2)在没有布局管理器(Main.java,ImageDialog.java)的JDialog中加载图像。 (取消注释'mn.showDialog(mn.frame,file);'行)。 完美的作品。 没有例外!
ImageIO.read()函数应该可以,因为在这种情况下2.没有错误(即使代码运行了20分钟)。 奇怪,在第一种情况下,layoutmanager阻止GC卸载未使用的图像...
1.case中的问题应该在CTR @ CardPrinter和addIDCard()@ CardPrinter中。 在点击率中,我使用OverlayLayout。 在2.case中,根本没有Layoutmanager。
Java版本是:Windows7 SP1上的1.7.0_80。
有人可以帮我吗?
提前谢谢你,丹尼尔
例外:
线程“ AWT-EventQueue-0”中的异常java.lang.OutOfMemoryError:java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:java.awt.image.DataBufferByte。(DataBufferByte.java:92)上的Java堆空间: 415)在java.awt.image.Raster.createWritableRaster(Raster.java:941)在javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1073)在javax.imageio.ImageReader.getDestination(ImageReader.java:2896)在com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)处的com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1066)(javax.imageio.ImageIO.read(在测试中javax.imageio.ImageIO.read(ImageIO.java:1308)的ImageIO.java:1448)在测试中IDCardLayout.loadPicture(IDCardLayout.java:128)的Test.CardPrinter.addIDCard(CardPrinter.java:142) CardPrinter。(CardPrinter.java:62)在测试中.CardPrinter.createDialog(CardPrinter.java:91)在测试中.Main $ 1.actionPerformed(Main.java:69)在javax.swing.Timer.fireActionPerformed( 在javax.swing.Timer $ DoPostEvent.run(Timer.java:244)在java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)在java.awt.EventQueue.dispatchEventImpl(EventQueue) .java:745)at java.awt.EventQueue.access $ 300(EventQueue.java:103)at java.awt.EventQueue $ 3.run(EventQueue.java:706)at java.awt.EventQueue $ 3.run(EventQueue.java :704),位于java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76),位于java.security.AccessController.doPrivileged(Native Method),位于java.awt,位于java.awt.EventQueue.dispatchEvent(EventQueue.java:715) .EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)at java.awt.EventDispatch java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)的EventDispatchThread.java:146)java.awt.EventDispatchThread.run(Event DispatchThread.java:91)
package test;
/*Main.java*/
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
JFrame frame;
//list files recursively, using a filter (pattern). If pattern=*, all files will be listed.
public static void listFilesRecurse(String fullpath, String pattern[], Vector<File> foundFiles) throws IOException {
File dir = new File(fullpath);
File list[] = dir.listFiles();
for(File f: list) {
if( !f.isDirectory() ) {
for(String pt: pattern) {
if(pt.equals("*")) {
foundFiles.add(f);
break;
}
else if( f.getAbsolutePath().toUpperCase().endsWith(pt.toUpperCase()) ) {
foundFiles.add(f);
break;
}
}
} else {
listFilesRecurse(f.getAbsolutePath(), pattern, foundFiles);
}
}
}
public static void main(String[] args) {
final Main mn = new Main();
final String pathtofiles = "\\path\\to\\files\\";
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Vector<File> list = new Vector<File>();
System.out.println("\nListing files ...");
try {
listFilesRecurse(pathtofiles, new String[]{"jpg", "png", "jpeg"}, list);
} catch (IOException e) {
e.printStackTrace();
}
for(int index=0; index<list.size(); index++) {
String file = list.get(index).getAbsolutePath();
System.out.println("\nLoading image - " + index + ": " + file);
//mn.showDialog(mn.frame, file);
CardPrinter cp=null;
try {
cp = CardPrinter.createDialog(mn.frame, "Max",
"Muster", "1122", "12345678", "01/2018", file);
} catch (Exception e) {
e.printStackTrace();
continue; //break; //return;
}
cp.setVisible(true);
cp.dispose();
}
}
};
final Timer myTimer = new Timer(100, task);
myTimer.setRepeats(true);
JFrame frame = new JFrame("JFrame Example");
mn.frame = frame;
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JLabel label = new JLabel("This is a label!");
JButton button = new JButton();
button.setText("Press me");
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
myTimer.start();
}
});
panel.add(label);
panel.add(button);
frame.add(panel);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//opens the dialog that display an image (file).
public void showDialog(JFrame fr, String file) {
ImageDialog imgd = new ImageDialog(fr, "Testdialog", file);
imgd.setSize(300, 300);
imgd.setModal(true);
imgd.setLocation(250, 250);
imgd.setVisible(true);
}
}
package test;
/*ImageDialog.java*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.Timer;
import org.monte.cmykdemo.CMYKJPEGImage;
public class ImageDialog extends JDialog {
String file;
public ImageDialog(JFrame frame, String title, String file) {
super(frame, title);
this.file = file;
//######For debugging only. This will close the dialog window after 300 ms (by calling ImageDialog.this.setVisible(false);).
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
ImageDialog.this.dispose();
}
};
Timer cl = new Timer(300, task);
cl.start();
//#######
}
//renders the picture on screen.
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
setRenderingHints(g2d);
BufferedImage img=null;
try {
img = loadPicture(this.file);
} catch (IOException e) {
e.printStackTrace();
}
g2d.setColor(Color.BLUE);
g2d.drawRect(0, 0, this.getWidth(), this.getHeight());
g2d.drawImage(img, 10, 10, 80, 80, null, null);
}
void setRenderingHints(Graphics2D g2) {
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
}
public static BufferedImage loadPicture(String fullpath) throws IOException {
System.out.println("\nloadPicture(): " + fullpath);
//BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( fullpath );
BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );
return img;
}
}
package test;
/*CardPrinter.java*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BorderFactory;
import javax.swing.JButton;
public class CardPrinter extends JDialog /*implements Printable*/ {
protected JPanel jp;
protected JTextField tx;
protected JLabel lblCounter;
protected IDCardLayout idcard;
protected String vorname, nachname, id, gueltig, bild;
protected String chipid;
protected CardPrinter(Window owner, String vorname, String nachname, String id, String chipid,
String gueltig, String bild /*, DataReceiver drv*/) throws IOException {
super((Window)owner, "Assign_ChipID_DialogObject");
this.bild = bild;
//this.datareceiver = drv;
setTitle("Assign ID");
setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
setResizable(false);
jp = new JPanel();
jp.setLayout(null);
jp.setOpaque(false);
addIDCard();
//setupButtons();
//setSize(this.getPreferredSize().width, this.getPreferredSize().height);
setSize(250, 250); //+++
setLocation(300, 300); //+++
//Overlay components: tx overlaps idcard
JPanel cnt = new JPanel();
cnt.setLayout(new OverlayLayout(cnt));
cnt.add(jp);
getContentPane().add(cnt);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//######For debugging only. This will close the dialog window after 300 ms (by calling CardPrinter.this.setVisible(false);).
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
CardPrinter.this.setVisible(false);
}
};
Timer closeWnd = new Timer(300, task);
closeWnd.start();
//######
}
//use this to create an instance of this class.
public static CardPrinter createDialog(Window owner, String vorname,
String nachname, String id, String chipid, String gueltig, String bild /*, DataReceiver drv*/) throws IOException {
return new CardPrinter(owner, vorname, nachname, id, chipid, gueltig, bild /*, drv*/);
}
protected void addIDCard() throws IOException {
int idcard_move_vert=15, idcard_move_hor=76;
tx = new JTextField(this.chipid, 8);
jp.add(tx);
tx.setBounds(idcard_move_hor+130, idcard_move_vert+6, 70, 20);
Border border = BorderFactory.createLineBorder(Color.RED);
tx.setBorder(border);
tx.requestFocus();
lblCounter = new JLabel("");
lblCounter.setBounds(idcard_move_hor+270, idcard_move_vert-6, 40, 30);
jp.add(lblCounter);
lblCounter.requestFocus();
System.out.println("\naddIDCard() ...");
BufferedImage picture = IDCardLayout.loadPicture(this.bild);
idcard = new IDCardLayout(/*this.vorname, this.nachname, this.id,*/ picture, this.bild /*, this.gueltig*/);
idcard.setLayout(null);
//idcard.setBounds(idcard_move_hor, idcard_move_vert, idcard.getPreferredSize().width, idcard.getPreferredSize().height);
idcard.setBounds(idcard_move_hor, idcard_move_vert, 50, 60);
idcard.setBorder( new LineBorder(Color.BLACK) );
jp.add(idcard);
//repaint();
}
}
package test;
/*IDCardLayout.java*/
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import org.monte.cmykdemo.CMYKJPEGImage;
public class IDCardLayout extends JPanel {
private BufferedImage bild;
private String bildfile;
public IDCardLayout(BufferedImage photo, String bildfile) {
this.bild = photo;
this.bildfile = bildfile;
}
/**
* Render graphics to the screen.
*/
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
System.out.println("\npaintComponent() ...");
prepareGraphics(g2d);
}
public static BufferedImage loadPicture(String fullpath) throws IOException {
//BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( f.getAbsolutePath() );
BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );
return img;
}
//changing the rendering hints has no effect on Outofmemory-exception.
protected void setRenderingHints(Graphics2D g2, boolean normalText) {
if(true) {
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
}
}
/**
* Renders graphics to the screen.
*/
protected void prepareGraphics(Graphics2D g2) {
setRenderingHints(g2, true);
double newHeight = 60;
double scwidth = ( ((double)newHeight / (double)this.bild.getHeight()) ) * (double)this.bild.getWidth();
System.out.println("\nprepareGraphics() ..." + this.bildfile);
g2.drawImage(this.bild, 5, 5,
(int)scwidth,
(int)newHeight,
null, null);
}
}
问题已经解决了。 我不再使用类OverlayLayout。 布局看起来完全不同,但现在可以使用了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.