OutOfMemoryError on OSF1

G

Guest

Learned Readers:

The following program runs out of memory on my OSF1
platform but seems to work OK on the NT, Solaris, and
Linux hosts I've got access to. Does anyone have any
ideas on what's going on and/or how to work around the
problem? TIA,

% uname -a
OSF1 sys1 V5.1 1885 alpha

% java -version
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition
Fast VM (build 1.4.1-2, native threads, mixed mode, 06/18/2003-17:51)

% java Display
0 free memory: 206817680
1 free memory: 206565520
2 free memory: 206318720
3 free memory: 206071920
4 free memory: 205808736
5 free memory: 205561936
6 free memory: 205315136
7 free memory: 205068336
....
2217 free memory: 2078272
2218 free memory: 1831472
2219 free memory: 1584672
2220 free memory: 1337872
2221 free memory: 1091072
2222 free memory: 827888
2223 free memory: 581088
2224 free memory: 334288
2225 free memory: 87488
2226 free memory: 518520832
2227 free memory: 518274032
2228 free memory: 518010848
2229 free memory: 517764048
.... <lots more mem-grow sequences ommitted>
4290 free memory: 2573488
4291 free memory: 2326688
4292 free memory: 2079728
4293 free memory: 1816544
4294 free memory: 1569744
4295 free memory: 1322944
4296 free memory: 1076144
4297 free memory: 829344
4298 free memory: 582544
4299 free memory: 335744
4300 free memory: 72560
java.lang.OutOfMemoryError
at java.awt.image.DataBufferInt.<init> DataBufferInt.java:41)
at java.awt.image.Raster.createPackedRaster(Raster.java:452)
at
java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1015)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:259)
at Display.<init>(Display.java:97)
at Display.main(Display.java:113)

Note: 200 * 300 = 60000 pixels required for each
Image, and the free memory differences between
displays tends to be 246800. It appears that for
some reason the gc couldn't run when there was only
72560 bytes available for the next Image. Any
ideas why??

Here's the contents of Display.java:

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;

class DisplayPanel extends JPanel
{
private Image curImage = null;

public void setDisplayImage (Image newImage)
{
curImage = newImage;
revalidate ();
repaint ();
}

public void paintComponent (Graphics g)
{
if (curImage == null)
return;

Rectangle r = getBounds ();
g.clearRect (0, 0, r.width, r.height);

g.drawImage (curImage, 0, 0, null);

curImage.flush (); // doesn't help on OSF1
curImage = null; // doesn't help
}
}

class Display extends JFrame
{
static long count = 0L;
static Runtime runtime = Runtime.getRuntime ();

Display () throws Exception // Exceptions from invokeAndWait
{
super ();

final DisplayPanel displayPanel = new DisplayPanel ();
displayPanel.setPreferredSize (new Dimension (200, 300));

getContentPane ().add (displayPanel);
setSize (200, 300);

setVisible (true);

final int rgb[] = new int[200 * 300];

int alpha = 0xff000000;
int red = 150, grn = 150, blu = 150;
int redInc = 2, grnInc = 3, bluInc = 5;

while (true)
{
int val = alpha + (red << 16) + (grn << 8) + blu;
for (int i = 0; i < 200 * 300; i++)
rgb = val;

red += redInc;
blu += bluInc;
grn += grnInc;

if (red > 250 || red < 50) redInc *= -1;
if (grn > 250 || grn < 50) grnInc *= -1;
if (blu > 250 || blu < 50) bluInc *= -1;

final BufferedImage im = new
BufferedImage (200, 300, BufferedImage.TYPE_INT_ARGB);
im.setRGB (0, 0, 200, 300, rgb, 0, 200);

SwingUtilities.invokeAndWait (new Thread ()
{
public void run ()
{
// setPriority (Thread.MIN_PRIORITY); // doesn't help
System.out.println (count++ + " free memory: " +
runtime.freeMemory ());
displayPanel.setDisplayImage (im);
// System.gc (); // doesn't help
// yield (); // doesn't help
}
});
}
}

public static void main (String args[]) throws Exception
{
new Display ();
}
}
 
G

Guest

Hmmmm.....so, you're saying to rearrange things as:

Runnable runner = new Runnable ()
{
S.o.p. (...);
displayPanel.setDisplayImage (im);
};
SwingUtilities.invokeAndWait (runner);
runner = null;

OK, I just ran it, and my long counter var made it all the way to
Long.MAX_VALUE without tossing the cookies. :)

YOU DA MAN! Thanks a million, or make that thanks a MAX_VALUE.
 
T

Thomas Hawtin

The following program runs out of memory on my OSF1
platform but seems to work OK on the NT, Solaris, and
Linux hosts I've got access to. Does anyone have any
ideas on what's going on and/or how to work around the
problem? TIA,

From another posting, you seem to have fixed your problems, but anyway...
Image, and the free memory differences between
displays tends to be 246800. It appears that for
some reason the gc couldn't run when there was only
72560 bytes available for the next Image. Any
ideas why??

You will get an OutOfMemoryError if the gc fails to free-up a certain
proportion of the heap, even when there is enough memory for the
allocation that caused it. Running the GC is very expensive. If it ran
for every few allocations with low memory the performs would be somewhat
underwhelming.
while (true)
{
[...]
final BufferedImage im = new
BufferedImage (200, 300, BufferedImage.TYPE_INT_ARGB);
im.setRGB (0, 0, 200, 300, rgb, 0, 200);

SwingUtilities.invokeAndWait (new Thread () {

No reason to create a Thread here, that you don't actually run. Runnable
is sufficient.

You are continually creating (but not flushing) images and queuing them
up for display. You happen to be lucky enough that thread running this
just happens to be running with priority one notch lower than the thread
reading off the queue.
public void run ()
{
// setPriority (Thread.MIN_PRIORITY); // doesn't help

Set the AWT Event Dispatch Thread (EDT) to min priority? No, I don't
suppose that'll help. :) Also Thread.setPriority might not work for a
started thread (well, it might not do anything anyway).

Tom Hawtin
 
R

Roedy Green

No reason to create a Thread here, that you don't actually run. Runnable
is sufficient.
Swing calls your Runnable.run but it does NOT create a new thread to
do it. It is much more efficient than starting a new thread.
 
G

Guest

OK, thank you to all who have replied. I thought
I'd fixed the problem, but it seems to be trickier
than I'd thought. The Thread that creates new
BufferedImages send 'em to be displayed via:

Image curImage = null;
Runtime runtime = Runtime.getRuntime ();

public void newImage (Image newImage)
{
curImage = newImage;
repaint ();
}

public void paintComponent (Graphics g)
{
Rectangle r = g.getBounds ();
System.out.println (runtime.freeMemory ());
g.displayImage (curImage, 0, 0, r.width, r.height, Color.black,
null);
curImage.flush ();
curImage = null;
r = null;
g = null;
}

When I run this on my OSF1 system, it displays
a couple thousand images but then tosses an
OOME in spite of printing out that there's tons of
memory available. So, according to Roedy's above
mentioned link, the GUI is running out of memory.

What am I missing as far as freeing things up??
I even tried putting in System.gc () calls, but to
no avail. And, I tried putting in a monitor instead
of null as the last arg to displayImage, but that
didn't seem to work either.
 
R

Roedy Green

int val = alpha + (red << 16) + (grn << 8) + blu;
for (int i = 0; i < 200 * 300; i++)
rgb = val;


Of course, if all you were trying to do was to produce a display that
changes shade frequently, you could just do that much more quickly
with a fillRect in your paintComponent and dispense with the Image
altogether. I assume though the real program does something more
interesting with the Image.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top