-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
1.4.1, 1.4.2
-
x86
-
windows_2000
Name: jk109818 Date: 08/13/2003
FULL PRODUCT VERSION :
This appears in j2sdk 1.4.1 but not in 1.4.0 or earlier versions. On the windows machine, java -version produces
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)
On the Linux machine:
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)
The bug does NOT appear in
(Windows 2000 machine)
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OS VERSION :
Microsoft Windows 2000, Version 5.00.2195
Also seen on Red Hat Linux 8.0 (uname -a produces
Linux <hostname> 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i
386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
If an ImageIcon obtained via deserialization, and then used to display an icon in a tree cell renderer, the icon is not painted, though enough space is set aside for the icon.
It seems this occurs because the getImageLoadStatus() method is returning the value 0, rather than one of the legal values from MediaTracker as specified in the API. I assume some code has changed from v1.4.0 to v1.4.1 which checks explicitly for the value MediaTracker.COMPLETE before painting the icon. The readObject method can be adapted to update this value as in the workaround below.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Save the source code for executable test case below as IconTest.java. Compile under jdk1.4.1 and execute under jdk1.4.1 with (for example)
java IconTest duke.gif
EXPECTED VERSUS ACTUAL BEHAVIOR :
The image provided on the command line would be displayed for leaf nodes in the default JTree.
A blank space (the same size as the specified image) was displayed for the leaf nodes.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
// File IconTest.java
import java.awt.* ;
import javax.swing.* ;
import javax.swing.tree.* ;
import java.io.* ;
public class IconTest {
public static void main(String[] args) {
ImageIcon icon = new ImageIcon(args[0]);
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("icon.ser"));
oos.writeObject(icon);
oos.close();
} catch (Exception exc) {
exc.printStackTrace();
}
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("icon.ser"));
icon = (ImageIcon) ois.readObject();
ois.close();
} catch (Exception exc) {
exc.printStackTrace();
}
final ImageIcon theIcon = icon ;
JFrame frame = new JFrame();
Container c = frame.getContentPane();
JTree tree = new JTree();
tree.setCellRenderer(new DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
JLabel label = (JLabel) super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (leaf) label.setIcon(theIcon);
return label ;
}
});
c.add(new JScrollPane(tree));
frame.setSize(200,400);
frame.setVisible(true);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Change the line in the above from
ImageIcon icon = new ImageIcon(args[0]);
to
ImageIcon icon = new SerializedImageIcon(args[0]);
and compile the following to the classpath:
import javax.swing.* ;
import java.awt.* ;
import java.awt.image.* ;
import java.io.* ;
public class SerializedImageIcon extends ImageIcon {
private transient int loadStatus = 0 ;
public SerializedImageIcon(String filename) {
super(filename);
}
public int getImageLoadStatus() {
return loadStatus == 0 ? super.getImageLoadStatus() : loadStatus ;
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
int w = s.readInt();
int h = s.readInt();
int[] pixels = (int[])(s.readObject());
if (pixels != null) {
Toolkit tk = Toolkit.getDefaultToolkit();
ColorModel cm = ColorModel.getRGBdefault();
setImage(tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w)));
loadStatus = MediaTracker.COMPLETE ;
}
}
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
int w = getIconWidth();
int h = getIconHeight();
Image image = getImage() ;
int[] pixels = image != null? new int[w * h] : null;
if (image != null) {
try {
PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
pg.grabPixels();
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
throw new IOException("failed to load image contents");
}
}
catch (InterruptedException e) {
throw new IOException("image load interrupted");
}
}
s.writeInt(w);
s.writeInt(h);
s.writeObject(pixels);
}
}
Release Regression From : 1.4.0_00
The above release value was the last known release where this
bug was known to work. Since then there has been a regression.
(Incident Review ID: 184636)
======================================================================
FULL PRODUCT VERSION :
This appears in j2sdk 1.4.1 but not in 1.4.0 or earlier versions. On the windows machine, java -version produces
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)
On the Linux machine:
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)
The bug does NOT appear in
(Windows 2000 machine)
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OS VERSION :
Microsoft Windows 2000, Version 5.00.2195
Also seen on Red Hat Linux 8.0 (uname -a produces
Linux <hostname> 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i
386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
If an ImageIcon obtained via deserialization, and then used to display an icon in a tree cell renderer, the icon is not painted, though enough space is set aside for the icon.
It seems this occurs because the getImageLoadStatus() method is returning the value 0, rather than one of the legal values from MediaTracker as specified in the API. I assume some code has changed from v1.4.0 to v1.4.1 which checks explicitly for the value MediaTracker.COMPLETE before painting the icon. The readObject method can be adapted to update this value as in the workaround below.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Save the source code for executable test case below as IconTest.java. Compile under jdk1.4.1 and execute under jdk1.4.1 with (for example)
java IconTest duke.gif
EXPECTED VERSUS ACTUAL BEHAVIOR :
The image provided on the command line would be displayed for leaf nodes in the default JTree.
A blank space (the same size as the specified image) was displayed for the leaf nodes.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
// File IconTest.java
import java.awt.* ;
import javax.swing.* ;
import javax.swing.tree.* ;
import java.io.* ;
public class IconTest {
public static void main(String[] args) {
ImageIcon icon = new ImageIcon(args[0]);
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("icon.ser"));
oos.writeObject(icon);
oos.close();
} catch (Exception exc) {
exc.printStackTrace();
}
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("icon.ser"));
icon = (ImageIcon) ois.readObject();
ois.close();
} catch (Exception exc) {
exc.printStackTrace();
}
final ImageIcon theIcon = icon ;
JFrame frame = new JFrame();
Container c = frame.getContentPane();
JTree tree = new JTree();
tree.setCellRenderer(new DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
JLabel label = (JLabel) super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (leaf) label.setIcon(theIcon);
return label ;
}
});
c.add(new JScrollPane(tree));
frame.setSize(200,400);
frame.setVisible(true);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Change the line in the above from
ImageIcon icon = new ImageIcon(args[0]);
to
ImageIcon icon = new SerializedImageIcon(args[0]);
and compile the following to the classpath:
import javax.swing.* ;
import java.awt.* ;
import java.awt.image.* ;
import java.io.* ;
public class SerializedImageIcon extends ImageIcon {
private transient int loadStatus = 0 ;
public SerializedImageIcon(String filename) {
super(filename);
}
public int getImageLoadStatus() {
return loadStatus == 0 ? super.getImageLoadStatus() : loadStatus ;
}
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
s.defaultReadObject();
int w = s.readInt();
int h = s.readInt();
int[] pixels = (int[])(s.readObject());
if (pixels != null) {
Toolkit tk = Toolkit.getDefaultToolkit();
ColorModel cm = ColorModel.getRGBdefault();
setImage(tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w)));
loadStatus = MediaTracker.COMPLETE ;
}
}
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
int w = getIconWidth();
int h = getIconHeight();
Image image = getImage() ;
int[] pixels = image != null? new int[w * h] : null;
if (image != null) {
try {
PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
pg.grabPixels();
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
throw new IOException("failed to load image contents");
}
}
catch (InterruptedException e) {
throw new IOException("image load interrupted");
}
}
s.writeInt(w);
s.writeInt(h);
s.writeObject(pixels);
}
}
Release Regression From : 1.4.0_00
The above release value was the last known release where this
bug was known to work. Since then there has been a regression.
(Incident Review ID: 184636)
======================================================================
- duplicates
-
JDK-4827074 ImageIcon serialization does not preload restored images
-
- Resolved
-