Search code examples
javaserializationtransient

Getting spotbug issue type SE_TRANSIENT_FIELD_NOT_RESTORED


I have one listner class 'A', which implements interface 'B' and 'B' extends Serializable class.

Now in class 'A',

  1. If I declare logger as transient as below:

    private final transient Logger logger = LoggerFactory.getLogger(getClass());

then spotbug reports error as below:

logger is transient but isn't set by deserialization
  1. If I declare logger as non-transient

    private final Logger logger = LoggerFactory.getLogger(getClass());

m getting below error:

Make "logger" transient or serializable.

how to resolve this problem ?


Solution

  • The problem is that deserialization doesn't follow the normal rules of object initialization, so the transient field will not be populated, and instead it will be null.

    The simplest solution is to make the field static, so it isn't a member of an instance. However, if you have a reason to make it an instance field, for example if you have a lot of subclasses, and you want your logging to be able to identify the actual class, then you need to make sure the transient field is populated when it is deserialized.

    This can be done with either readResolve() or readObject(ObjectInputStream). For example:

    private Object readResolve() throws ObjectStreamException {
        logger = LoggerFactory.getLogger(getClass());
        return this;
    }
    

    or

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject()
        logger = LoggerFactory.getLogger(getClass())
    }
    

    In both cases, the field logger can no longer be final.