Should a Log4J logger be declared as transient?

19,374

Solution 1

How about using a static logger? Or do you need a different logger reference for each instance of the class? Static fields are not serialized by default; you can explicitly declare fields to serialize with a private, static, final array of ObjectStreamField named serialPersistentFields. See Oracle documentation

Added content: As you use getLogger(getClass()), you will use the same logger in each instance. If you want to use separate logger for each instance you have to differentiate on the name of the logger in the getLogger() -method. e.g. getLogger(getClass().getName() + hashCode()). You should then use the transient attribute to make sure that the logger is not serialized.

Solution 2

The logger must be static; this would make it non-serializable.

There's no reason to make logger non-static, unless you have a strong reason to do it so.

Solution 3

If you really want to go the transient approach you will need to reset the log when your object is deserialized. The way to do that is to implement the method:

 private void readObject(java.io.ObjectInputStream in) 
   throws IOException, ClassNotFoundException;

The javadocs for Serializable has information on this method.

Your implementation of it will look something like:

 private void readObject(java.io.ObjectInputStream in) 
     throws IOException, ClassNotFoundException {
   log = Logger.getLogger(...);
   in.defaultReadObject();
 }

If you do not do this then log will be null after deserializing your object.

Solution 4

Either declare your logger field as static or as transient.

Both ways ensure the writeObject() method will not attempt to write the field to the output stream during serialization.

Usually logger fields are declared static, but if you need it to be an instance field just declare it transient, as its usually done for any non-serializable field. Upon deserialization the logger field will be null, though, so you have to implement a readObject() method to initialize it properly.

Solution 5

Try making the Logger static instead. Than you don't have to care about serialization because it is handled by the class loader.

Share:
19,374
Vihung
Author by

Vihung

Basic b*tch Java Web Applications Developer - Spring Boot, AWS, Angular, Bootstrap. Mac and iPhone user. Highly opinionated about Design/User Experience/Usability.

Updated on June 14, 2022

Comments

  • Vihung
    Vihung almost 2 years

    I am using Java 1.4 with Log4J.

    Some of my code involves serializing and deserializing value objects (POJOs).

    Each of my POJOs declares a logger with

    private final Logger log = Logger.getLogger(getClass());
    

    The serializer complains of org.apache.log4j.Logger not being Serializable.

    Should I use

    private final transient Logger log = Logger.getLogger(getClass());
    

    instead?