Discussions
Categories
- 197.2K All Categories
- 2.5K Data
- 546 Big Data Appliance
- 1.9K Data Science
- 450.8K Databases
- 221.9K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 552 MySQL Community Space
- 479 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.1K ORDS, SODA & JSON in the Database
- 555 SQLcl
- 4K SQL Developer Data Modeler
- 187.2K SQL & PL/SQL
- 21.4K SQL Developer
- 296.3K Development
- 17 Developer Projects
- 139 Programming Languages
- 293K Development Tools
- 110 DevOps
- 3.1K QA/Testing
- 646.1K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 158 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.2K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 19 Java Essentials
- 162 Java 8 Questions
- 86K Java Programming
- 81 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 205 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 468 LiveLabs
- 39 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 175 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 233 Portuguese
Outofmemory exception loading images

Dear community,
i have a problem loading image files.
There are 2 cases, i've tested. The problem occures only in the first one. In both cases a JDialog-window apears that displays a
downscaled image. After 300ms this window closes automatically (there is a timer in the constructor of ImageDialog and CardPrinter; this is only for debugging).
In the production version, the programm must be able to load 30-40 images (one by one) in a JDialog. The user types some text, and clicks on a button to show the next image.
To load the images i use ImageIO.read() in both cases. Alternatively i used CMYKJPEGImage (http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/)
but it also produces the exception.
In Main there is myTimer that continusly opens the JDialog with an image-file (listFilesRecurse() should be called with an absolute path by setting the variable pathtofiles).
Case 1) loading images in JDialog with overlay layout manager (Main.java, CardPrinter.java, IDCardLayout.java).
For this, the lines from 'CardPrinter cp=null;' to 'cp.dispose();' in Main.java must be uncommented. The tricky part is in addIDCard()@CardPrinter.
Here will be the layout built up. After this paintComponent()@IDCardLayout will be called, if the content of the dialog-window should be actualised.
It seems, that the loaded images won't be destroyed, and the memory gets full (in Window's Taskmanager the memory usage can be seen).
Case 2) loading images in a JDialog with no layout manager (Main.java, ImageDialog.java).
(Uncomment the line 'mn.showDialog(mn.frame, file);').
Works perfect. No exceptions!
The function ImageIO.read() should be ok, because in the 2. case, there was no errors (even if the code runs for 20 minutes).
It's strange, it seems in the first case the layoutmanager prevents GC to unload the unused images...
The Java version is: 1.7.0_80 on Windows7 SP1.
Can somebody help me please?
Thank you in advance,
Daniel
The exception:
Exception in thread "AWT-EventQueue-0" 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:941)
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:1066)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1308)
at test.IDCardLayout.loadPicture(IDCardLayout.java:128)
at test.CardPrinter.addIDCard(CardPrinter.java:142)
at test.CardPrinter.<init>(CardPrinter.java:62)
at test.CardPrinter.createDialog(CardPrinter.java:91)
at test.Main$1.actionPerformed(Main.java:69)
at javax.swing.Timer.fireActionPerformed(Timer.java:312)
at javax.swing.Timer$DoPostEvent.run(Timer.java:244)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at 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)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.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.
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);
}
}
Answers
-
That is a lot of code to go through, so I am not.
Let me ask you this: I see you have a portion that is marked as recursive, do you recursively call the loading of the images? If you do therein is your problem.
-
Have you tried to define your Layout at level of the class as static attribute?
You only require one.Each time you use a BufferedImage, after painting the image invokes flush
picture.flush();
picture = null;
---
RuGI
-
Thanx for the answer.
Can you tell me, which lines are recursive?
It was not my intent to do a recursive call. If so, this could maybe the problem.
-
Yes, but didn't help.
-
The problem is solved. I don't use the class OverlayLayout anymore. The layout looks quite different, but now it works.