Bug 14144 - Serialisation bug with abstract classes
Summary: Serialisation bug with abstract classes
Status: RESOLVED FIXED
Alias: None
Product: classpath
Classification: Unclassified
Component: classpath (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: 0.90
Assignee: Olivier Jolly
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-02-14 09:22 UTC by Christian Stüllenberg
Modified: 2006-02-16 11:09 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2004-11-01 12:41:52


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christian Stüllenberg 2004-02-14 09:22:41 UTC
I think I found a bug in the serialisation/deserialisation of objects
that inherit from an abstract class.

Please have a look at the following testcase:

File test10/Element.java:
package test10;

import java.util.*;

abstract class Element {
    private Set set = new TreeSet();

    public void add(String t) {
	System.out.println("act1");
	set.add(t);
	System.out.println("act2");
    }
}


File test10/ConcreteElement.java:
package test10;

import java.io.*;
import java.util.*;

class ConcreteElement extends Element implements Serializable {
    void addSomethingTo(Element oei) {
	oei.add("TEST");
    }

    public static void main(String[] args) {
        try {
            ConcreteElement e1 = new ConcreteElement();
            ConcreteElement e2 = new ConcreteElement();
            
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream po = new ObjectOutputStream(out);
            po.writeObject(e1);
            
            byte[] b = out.toByteArray();
            
            ByteArrayInputStream in = new ByteArrayInputStream(b);
            ObjectInputStream pi = new ObjectInputStream(in);
            Object o = pi.readObject();
            ConcreteElement l = (ConcreteElement)o;
            
            e2.addSomethingTo(l);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Now I've compiled the stuff with javac (1.4.2) and it runs without any
errors.  Then I jarred the two classes into an jar file and used
 gcj --main=test10.ConcreteElement -o test10 test10.jar
to compile an executable, but that gives me the following error:
act1
java.lang.NullPointerException
   at _ZN4java4lang11VMThrowable16fillInStackTraceEPNS0_9ThrowableE
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang9Throwable16fillInStackTraceEv
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang9ThrowableC1EPNS0_6StringE
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang9ThrowableC1Ev (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang9ExceptionC1Ev (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang16RuntimeExceptionC1Ev (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN4java4lang20NullPointerExceptionC1Ev
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _Jv_AllocObject (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _Z10_Jv_selectiP6fd_setS0_S0_P7timeval (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN3gnu3gcj7runtime11FirstThread9call_mainEv
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _ZN3gnu3gcj7runtime11FirstThread3runEv (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _Z13_Jv_ThreadRunPN4java4lang6ThreadE (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at _Z11_Jv_RunMainPN4java4lang5ClassEPKciPS4_b
(/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at JvRunMain (/site.opt/gcc-3.4/lib/libgcj.so.4.0.0)
   at __libc_start_main (/lib/libc.so.6)
   at _start (Unknown Source)


If the class test10.Element is not declared as abstract, the native
compiled executable again works without any errors.

I was using using: $> gcj --version
gcj (GCC) 3.4 20031210 (experimental)
on a linux box (don't know, if you need this info) for the above error message,
but it is still the same with 'gcj (GCC) 3.4.0 20040206 (prerelease)' and '3.5.0
cvs' from 10 Feb 2004.

Christian
Comment 1 Andrew Pinski 2004-02-14 20:30:18 UTC
Confirmed.
java.lang.NullPointerException
   at test10.ConcreteElement.addSomethingTo(test10.Element) (/home/gates/pinskia/src/
gnu/gcctest/pr14144/test10/ConcreteElement.java:10)
   at test10.ConcreteElement.main(java.lang.String[]) (/home/gates/pinskia/src/gnu/
gcctest/pr14144/test10/ConcreteElement.java:28)
Comment 2 Olivier Jolly 2006-02-16 10:47:52 UTC
The problem comes from the choice of the constructor during the deserialization process. Up to now, the first non abstract, non serializable constructor in the super classes were choosen. So it incorrectly skipped all abtract constructor (which, in your case, is executing "set = new TreeSet();").
The contructor choice algorithm has been updated to take this choice in account and is available in the current CVS version of classpath.
Christian, if you still have this piece of code around, can you confirm the fix ?