Re: [classlib][serialization] Conditional object replacement in ObjectInputStream - bug in RI?
Hi, I have posted the patch for HARMONY-1920. I will be glad if some committer take a look at it. I mean the more powerfull one than me :-/ I've also tried to resolve HARMONY-1921, but it seems a good luni expertice is required for that. So it may be the good task for local luni exprets floating around. With best regards, 2006/10/20, Alexei Zakharov <[EMAIL PROTECTED]>: Hi Mikhail, I don't see any problems with the RI behavior here. The spec says about the ObjectInputStream#resolveClass() method: "This method will be invoked only once for each unique class in the stream." So your TestObjectInputStream#resolveClass() will be called only once. And all serialized objects in the stream that have original type a.TestClass will be deserialized to the type b.TestClass and it is the correct behavior. This way, ClassCastException at line >try { >a.TestClass to4 = (a.TestClass) ois.readObject(); is expected since you are trying to cast the object of type b.TestClass to incompatible type a.TestClass. Does it makes sense? Thanks, 2006/10/19, Mikhail Markov <[EMAIL PROTECTED]>: > Hi! > > I've recently filed 2 JIRAs (HARMONY-1920 and HARMONY 1921) related to the > object replacement in ObjectInputStream by means of resolveObject() method > and during experimenting with the tests, created the test which replaces the > object according to some rule (see the code at the bottom of the message). > Unexpectedly it fails on RI with the output: > > TestObjectInputStream.resolveClass() is called. > 1-st read passed. > 2-nd read failed with exception: java.lang.ClassCastException: b.TestClass > > This output indicates that RI performs caching for object replacements and > second read just did not call resolveClass() method from > TestObjectInputStream. > > I did not find any info about this case in serialization specification > and not quite sure if this behaviour is correct. Is this a bug in RI? > If not then this case should be also taken into account while fixing > HARMONY-1921 JIRA. > > - Test.java - > import java.io.*; > > public class Test { >public static void main(String[] args) throws Exception { >a.TestClass to1 = new a.TestClass(); >to1.i = 555; >a.TestClass to2 = new a.TestClass(); >to2.i = 777; >ByteArrayOutputStream baos = new ByteArrayOutputStream(); >ObjectOutputStream oos = new ObjectOutputStream(baos); >oos.writeObject(to1); >oos.writeObject(to2); >oos.flush(); >byte[] bytes = baos.toByteArray(); >ByteArrayInputStream bais = new ByteArrayInputStream(bytes); >ObjectInputStream ois = new TestObjectInputStream(bais); > >try { >b.TestClass to3 = (b.TestClass) ois.readObject(); > >if (to3.i != to1.i) { >System.out.println("1-st read failed. Expected: " + to1.i + > ", got: " + to3.i); >} else { >System.out.println("1-st read passed."); >} >} catch (Exception ex) { >System.out.println("1-st read failed with exception: " + ex); >} > >try { >a.TestClass to4 = (a.TestClass) ois.readObject(); > >if (to4.i != to2.i) { >System.out.println("2-nd read failed. Expected: " + to2.i + > ", got: " + to4.i); >} else { >System.out.println("2-nd read passed."); >} >} catch (Exception ex) { >System.out.println("2-nd read failed with exception: " + ex); >} >} > >static class TestObjectInputStream extends ObjectInputStream { >private boolean replaced = false; > >public TestObjectInputStream(InputStream in) throws IOException { >super(in); >} > >protected Class resolveClass(ObjectStreamClass desc) >throws IOException, ClassNotFoundException { >if (desc.getName().equals("a.TestClass")) { >System.out.println("TestObjectInputStream.resolveClass() is > called."); > >if (!replaced) { >replaced = true; >return b.TestClass.class; >} else { >return a.TestClass.class; >} >} >return super.resolveClass(desc); >} >} > } > - a/TestClass.java - > package a; > > import java.io.Serializable; > > public class TestClass implements Serializable { >private static final long serialVersionUID = 1L; >public int i = 0; > } > - b/TestClass.java - > package b; > > import java.io.Serializable; > > public class TestClass implements Serializable { >private static final long serialVersionUID = 1L; >public int i = 0; > } > - -- Alexei
Re: [classlib][serialization] Conditional object replacement in ObjectInputStream - bug in RI?
Hi Mikhail, I don't see any problems with the RI behavior here. The spec says about the ObjectInputStream#resolveClass() method: "This method will be invoked only once for each unique class in the stream." So your TestObjectInputStream#resolveClass() will be called only once. And all serialized objects in the stream that have original type a.TestClass will be deserialized to the type b.TestClass and it is the correct behavior. This way, ClassCastException at line try { a.TestClass to4 = (a.TestClass) ois.readObject(); is expected since you are trying to cast the object of type b.TestClass to incompatible type a.TestClass. Does it makes sense? Thanks, 2006/10/19, Mikhail Markov <[EMAIL PROTECTED]>: Hi! I've recently filed 2 JIRAs (HARMONY-1920 and HARMONY 1921) related to the object replacement in ObjectInputStream by means of resolveObject() method and during experimenting with the tests, created the test which replaces the object according to some rule (see the code at the bottom of the message). Unexpectedly it fails on RI with the output: TestObjectInputStream.resolveClass() is called. 1-st read passed. 2-nd read failed with exception: java.lang.ClassCastException: b.TestClass This output indicates that RI performs caching for object replacements and second read just did not call resolveClass() method from TestObjectInputStream. I did not find any info about this case in serialization specification and not quite sure if this behaviour is correct. Is this a bug in RI? If not then this case should be also taken into account while fixing HARMONY-1921 JIRA. - Test.java - import java.io.*; public class Test { public static void main(String[] args) throws Exception { a.TestClass to1 = new a.TestClass(); to1.i = 555; a.TestClass to2 = new a.TestClass(); to2.i = 777; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(to1); oos.writeObject(to2); oos.flush(); byte[] bytes = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new TestObjectInputStream(bais); try { b.TestClass to3 = (b.TestClass) ois.readObject(); if (to3.i != to1.i) { System.out.println("1-st read failed. Expected: " + to1.i + ", got: " + to3.i); } else { System.out.println("1-st read passed."); } } catch (Exception ex) { System.out.println("1-st read failed with exception: " + ex); } try { a.TestClass to4 = (a.TestClass) ois.readObject(); if (to4.i != to2.i) { System.out.println("2-nd read failed. Expected: " + to2.i + ", got: " + to4.i); } else { System.out.println("2-nd read passed."); } } catch (Exception ex) { System.out.println("2-nd read failed with exception: " + ex); } } static class TestObjectInputStream extends ObjectInputStream { private boolean replaced = false; public TestObjectInputStream(InputStream in) throws IOException { super(in); } protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (desc.getName().equals("a.TestClass")) { System.out.println("TestObjectInputStream.resolveClass() is called."); if (!replaced) { replaced = true; return b.TestClass.class; } else { return a.TestClass.class; } } return super.resolveClass(desc); } } } - a/TestClass.java - package a; import java.io.Serializable; public class TestClass implements Serializable { private static final long serialVersionUID = 1L; public int i = 0; } - b/TestClass.java - package b; import java.io.Serializable; public class TestClass implements Serializable { private static final long serialVersionUID = 1L; public int i = 0; } - -- Alexei Zakharov, Intel Enterprise Solutions Software Division - Terms of use : http://incubator.apache.org/harmony/mailing.html To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
[classlib][serialization] Conditional object replacement in ObjectInputStream - bug in RI?
Hi! I've recently filed 2 JIRAs (HARMONY-1920 and HARMONY 1921) related to the object replacement in ObjectInputStream by means of resolveObject() method and during experimenting with the tests, created the test which replaces the object according to some rule (see the code at the bottom of the message). Unexpectedly it fails on RI with the output: TestObjectInputStream.resolveClass() is called. 1-st read passed. 2-nd read failed with exception: java.lang.ClassCastException: b.TestClass This output indicates that RI performs caching for object replacements and second read just did not call resolveClass() method from TestObjectInputStream. I did not find any info about this case in serialization specification and not quite sure if this behaviour is correct. Is this a bug in RI? If not then this case should be also taken into account while fixing HARMONY-1921 JIRA. - Test.java - import java.io.*; public class Test { public static void main(String[] args) throws Exception { a.TestClass to1 = new a.TestClass(); to1.i = 555; a.TestClass to2 = new a.TestClass(); to2.i = 777; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(to1); oos.writeObject(to2); oos.flush(); byte[] bytes = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new TestObjectInputStream(bais); try { b.TestClass to3 = (b.TestClass) ois.readObject(); if (to3.i != to1.i) { System.out.println("1-st read failed. Expected: " + to1.i + ", got: " + to3.i); } else { System.out.println("1-st read passed."); } } catch (Exception ex) { System.out.println("1-st read failed with exception: " + ex); } try { a.TestClass to4 = (a.TestClass) ois.readObject(); if (to4.i != to2.i) { System.out.println("2-nd read failed. Expected: " + to2.i + ", got: " + to4.i); } else { System.out.println("2-nd read passed."); } } catch (Exception ex) { System.out.println("2-nd read failed with exception: " + ex); } } static class TestObjectInputStream extends ObjectInputStream { private boolean replaced = false; public TestObjectInputStream(InputStream in) throws IOException { super(in); } protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (desc.getName().equals("a.TestClass")) { System.out.println("TestObjectInputStream.resolveClass() is called."); if (!replaced) { replaced = true; return b.TestClass.class; } else { return a.TestClass.class; } } return super.resolveClass(desc); } } } - a/TestClass.java - package a; import java.io.Serializable; public class TestClass implements Serializable { private static final long serialVersionUID = 1L; public int i = 0; } - b/TestClass.java - package b; import java.io.Serializable; public class TestClass implements Serializable { private static final long serialVersionUID = 1L; public int i = 0; } - Mikhail Markov Intell Middleware Products Division