-
Bug
-
Resolution: Fixed
-
P2
-
1.4.0
-
beta
-
generic, x86
-
generic, windows_nt
-
Verified
Name: vuR10080 Date: 07/13/2000
###@###.### 2000-07-13
A simple AWT GUI (Frame + empty ScrollPane) is serialized under 1.3
and is being deserialized under 1.4. Deserialization fails with an
ArrayStoreException.
----- GUI.java -----
import java.awt.*;
public class GUI extends Frame {
public GUI() {
ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
add(sp, "Center");
setSize(200, 200);
}
}
----- WriteTest.java -----
import java.io.*;
public class WriteTest {
public static void main(String[] args) {
String serFileName = "gui.ser";
if (args.length != 0)
serFileName = args[0];
GUI gui = new GUI();
gui.setVisible(true); // and wait for peer creation to complete
try { Thread.sleep(3000); } catch (Exception e) {}
try {
FileOutputStream f = new FileOutputStream(serFileName);
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(gui);
s.flush();
System.err.println("Serialization PASSED");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
----- ReadTest.java -----
import java.io.*;
public class ReadTest {
public static void main(String[] args) {
String serFileName = "gui.ser";
if (args.length != 0)
serFileName = args[0];
GUI gui = null;
try {
FileInputStream f = new FileInputStream(serFileName);
ObjectInputStream s = new ObjectInputStream(f);
gui = (GUI)s.readObject();
System.err.println("Deserialization PASSED");
}
catch (Exception e) {
e.printStackTrace();
}
gui.setVisible(true);
}
}
======================================================================
Name: vuR10080 Date: 07/13/2000
###@###.### 2000-07-13
Here are additional gory details. In 1.4 ScrollPane was extended with
a new field and readObject/writeObject were introduced to handle that
additional data. The readObject method is highly idiomatic. If
ScrollPane.readObject is trimmed down to do just defaultReadObject -
deserialization in 1.4 works ok.
I have added a good deal of debugging prints to ObjectInputStream and
discovered that ScrollPane.readObject somehow manages to read past the
object boundary and render ObjectInputStream out of sync. The log
looks like this when trimmed down to essentials:
=== calling inputClassFields on class java.awt.Component === <-- Frame
=== calling inputClassFields on class java.awt.Container ===
0: I containerSerializedDataVersion
1: I ncomponents
2: [Ljava/awt/Component; component <-- uwe: note the
3: Ljava/awt/LightweightDispatcher; dispatcher <-- layout!
4: Ljava/awt/LayoutManager; layoutMgr
5: Ljava/awt/Dimension; maxSize
{
java.awt.Component[] java.awt.Container.component { <-- Frame content
array length = 4
@[0] {
=== calling inputClassFields on class java.awt.Component === <-- ScrollPane
=== calling inputClassFields on class java.awt.Container ===
=== calling inputClassFields on class java.awt.ScrollPane ===
!!! uwe: here ScrollPane consumes null object that is the component[1]
}
@[1] null <-- uwe: component[2] in fact
@[2] null <-- uwe: component[3] in fact
@[3] {
!!!! uwe: we need to read component[3] here, but the stream is out of
!!!! sync so the LightweightDispatcher dispatcher (next in layout) is read
=== calling inputClassFields on class java.awt.LightweightDispatcher ===
} // component[3]
} // Component[] component
} // end of java.awt.Container
java.lang.ArrayStoreException
at java.io.ObjectInputStream.inputArray(../../../src/share/classes/java/io/ObjectInputStream.java:1156)
at java.io.ObjectInputStream.readObject(../../../src/share/classes/java/io/ObjectInputStream.java:374)
at java.io.ObjectInputStream.inputClassFields(../../../src/share/classes/java/io/ObjectInputStream.java:2281)
at java.io.ObjectInputStream.defaultReadObject(../../../src/share/classes/java/io/ObjectInputStream.java:526)
at java.awt.Container.readObject(Container.java:1797)
at java.lang.reflect.Method.invoke(Native Method)
at java.io.ObjectInputStream.invokeObjectReader(../../../src/share/classes/java/io/ObjectInputStream.java:2231)
at java.io.ObjectInputStream.inputObject(../../../src/share/classes/java/io/ObjectInputStream.java:1428)
at java.io.ObjectInputStream.readObject(../../../src/share/classes/java/io/ObjectInputStream.java:386)
at java.io.ObjectInputStream.readObject(../../../src/share/classes/java/io/ObjectInputStream.java:236)
at ReadTest.main(ReadTest.java:15)
java.lang.NullPointerException
at ReadTest.main(ReadTest.java:21)
Exception in thread "main"
So what happens is that ScrollPane.readObject calls s.readObject to
fetch optional data (if any) and this call is somehow allowed to
gobble the Frame.component[1] null object. Subsequently, when
Frame.component[3] is being read, the LightweightDispatcher object,
that follows the component[] array in the class layout, is read
instead - and than exception occurs when we try to store deserialized
LightweightDispatcher as the fourh element of component[] array.
======================================================================
- duplicates
-
JDK-4352200 jck_regr: api/java_awt/serialization/descriptions.html#Component
-
- Closed
-
-
JDK-4352247 jck_regr: api/java_awt/serialization/descriptions.html#Container
-
- Closed
-
-
JDK-4352264 jck_regr: api/java_awt/serialization/descriptions.html#ScrollPane
-
- Closed
-
-
JDK-4356134 jck_regr: api/java_awt/Event/serialization/descriptions.html#Events
-
- Closed
-
-
JDK-4356140 jck_regr: api/java_awt/serialization/descriptions.html#Frame
-
- Closed
-
-
JDK-4356147 jck_regr: api/java_awt/serialization/descriptions.html#Window
-
- Closed
-
-
JDK-4356152 jck_regr: api/java_awt/serialization/descriptions.html#MediaTracker
-
- Closed
-
- relates to
-
JDK-4360508 Better serialization support for class evolution that introduces optional data
-
- Closed
-