I have the following (doctored) class in a system I'm working on and Findbugs is generating a SE_BAD_FIELD warning and I'm trying to understand why it would say that before I fix it in the way that I thought I would. The reason I'm confused is because the description would seem to indicate that I had used no other non-serializable instance fields in the class but bar.model.Foo is also not serializable and used in the exact same way (as far as I can tell) but Findbugs generates no warning for it.
import bar.model.Foo;
import java.io.File;
import java.io.Serializable;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Demo implements Serializable {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final File file;
private final List<Foo> originalFoos;
private Integer count;
private int primitive = 0;
public Demo() {
for (Foo foo : originalFoos) {
this.logger.debug(...);
}
}
...
}
My initial blush at a solution is to get a logger reference from the factory right as I use it:
public DispositionFile() {
Logger logger = LoggerFactory.getLogger(this.getClass());
for (Foo foo : originalFoos) {
this.logger.debug(...);
}
}
That doesn't seem particularly efficient, though.
Thoughts?
FindBugs is misleading you in this particular case because the org.slf4j.Logger interface is not marked as java.io.Serializable. However, SLF4J logger implementations that ship with SLF4J all support serialization out-of-the-box. Try it. You'll see that it works.
Here is an excerpt from the SLF4j FAQ:
See also http://slf4j.org/faq.html#declared_static
Firstly, don't optimize prematurely. It may be that
LoggerFactory.getLogger()
is fast enough, and contributes no significant overhead to execution time. If in doubt, profile it.Secondly, the reason that findbugs isn't complaining about the use of
Foo
is because the class doesn't have a field of typeFoo
, it has a field of typeList
. The generics are erased at compile time, there is no actual reference toFoo
in the class, as far as the field definition is concerned. At runtime, the fact thatFoo
is non-serializable would cause an exception if you tried to serialize an instance of theDemo
class, but findbugs can't know this.My first reaction would be to make the
Logger
a static field, rather than an instance field. Should work fine in this situation.I don't want things to take off on a tangent, but have you considered the conventional initialization of loggers?
If you don't really need different loggers for each instance (which is unusual), the problem would go away.
By the way, the author of SL4J said (in a critique of Log4J wrappers like commons-logging),
That would suggest that your alternative idea of getting the logger each time you need it is not recommended.
My initial reaction is to wonder if it even makes sense to serialize a Logger instance in your object. When you deserialize it later, is it really all that fair to expect the Logger's environment to be correct? I think I would rather just go with this and call it a day: