Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FindBugs - SE_BAD_FIELD rule, why it ignores java.lang.Object?

From the description of SE_BAD_FIELD:

Non-transient non-serializable instance field in serializable class

This Serializable class defines a non-primitive instance field which is neither transient, Serializable, or java.lang.Object, and does not appear to implement the Externalizable interface or the readObject() and writeObject() methods. Objects of this class will not be deserialized correctly if a non-Serializable object is stored in this field.

Why is java.lang.Object an exception to the rule?

like image 959
boniek Avatar asked May 05 '11 14:05

boniek


2 Answers

Because everything can be deserialized back into an java.lang.Object as every class in java extends java.lang.Object. If you manage to serialize an object which has a non serializable field you have no way of knowing the class of that field on deserialization. Because every class is an object you can always fall back on the Object class.

    class NonSerializableUser {}
    class SerializableUser implements Serializable{}

    class SomeObject implements Serializable{
        public NonSerializableUser nonUser;
        public SerializableUser user;
        public Object nonUserObj;

        public SomeObject(SerializableUser u, NonSerializableUser uu, NonSerializableUser uuu){
            user = u;
            nonUser = uu;
            nonUserObj = uuu;
       }
    }

In this example deserializing this class would result in nonUser being null, user being the correct SerializableUser class instance, and nonUserObj would be non null however it will have lost all the NonSerializableClass methods and fields, they will not have been serialized. The only parts of that instance that get serialized are the methods and fields that belong to Object.

It's worth noting that a lot of serialization libraries (ObjectOutputStream for example) will complain about the non serializable class and won't serialize this object in the first place. This is why I left out the details of the serialization/deserialzation step. However a lot of xml frameworks will still serialize these classes and this tends to be the situation where this bug rears it's head.

like image 102
Jberg Avatar answered Nov 15 '22 06:11

Jberg


The number of false positives would be potentially high, as

public void writeIt(Object o, ObjectOutputStream oos) {
    oos.writeObject(o);
}

could be perfectly fine, as the caller always passes in an instance of a derived class that is Serializable.

Now the question is, why isn't the above method signature

public void writeIt(Serializable o, ObjectOutputStream oos) {
    oos.writeObject(o);
}

the answer is that then all kinds of objects defined by interfaces passed in as the first parameter would fail to compile.

such as

Map m = .....
writeIt(m, oos);

so the value of catching serializing java.lang.Object (which is probably an exceedingly rare event) is not worth the false positive impact.

like image 42
MeBigFatGuy Avatar answered Nov 15 '22 06:11

MeBigFatGuy