Reputation: 1713
I'm the only maintainer on a codebase where logging is done using Apache commons logging.
All classes contains these two imports:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Then a lot of classes contains non static log instantiation like this:
/** The log. */
private Log log = LogFactory.getLog(Xyz.class);
Can this be justified?
Can I safely change all these to static calls?
EDIT Regarding the special cases where it can (apparently) be handy: my question is really more "Can non static log all over the codebase be justified?"
Upvotes: 8
Views: 1730
Reputation: 19320
Here is an article that implies the opposite. In fact, in complex situations, class loading issues can arise with static loggers in libraries. So yes, non-static loggers can be justified.
However consider the case when a class using "private static Log log = ..." is deployed via a ClassLoader that is in the ancestry of multiple supposedly independent "applications". In this case, the log member is initialised only once, because there is only one copy of the class. That initialisation (typically) occurs the first time any code tries to instantiate that class or call a static method on it. When initialisation of the class occurs, what should the log member be set to?
http://wiki.apache.org/commons/Logging/StaticLog
Upvotes: 0
Reputation: 7705
One instance were a non-static logger is handy is some sort of a base class that provides a log instance to child classes (as a convenience). Consider the following example:
public abstract class Pet
{
protected Log log;
public Pet()
{
log = LogFactory.getLog(this.getClass());
}
public void wash()
{
log.info("Get the hose.");
}
...
}
public class Cat extends Pet
{
...
public void doSomethingUseful()
{
log.warn("I can't, I am a cat.");
}
}
In this example, the logging will be from the "Cat" log instance. Is this a valid justification for not using a static logger? Maybe not for messages logged from the Cat class, but messages logged from the Pet class under the Cat log instance could be helpful.
Upvotes: 2
Reputation: 49744
You have to be extra careful with having non-static loggers initialised the way your code snippet is doing in Serializable
classes.
Firstly because Log
isn't serializable, so any attempt of serializing your class will fail too. If you declare your logger transient
then, as is the logical thing to do, your log
field will not be initialised after deserialization, so you'll get an NPE
while trying to log stuff. Not a very nice situation.
So to sum it up, you can have non-static loggers if you prefer, but make sure they are initialised before you use them. But apart from that, I wouldn't worry much about non-static loggers, most logging implementations will always return the same logger object anyway (log4j definitely does).
Upvotes: 5
Reputation: 72284
It depends. This is from the documentation:
Note that for application code, declaring the log member as "static" is more efficient as one Log object is created per class, and is recommended. However this is not safe to do for a class which may be deployed via a "shared" classloader in a servlet or j2ee container or similar environment. If the class may end up invoked with different thread-context-classloader values set then the member must not be declared static. The use of "static" should therefore be avoided in code within any "library" type project.
Upvotes: 8