We used
to recommend that loggers members be declared as instance variables instead of static. After further analysis, we no longer recommend one approach over the other.
Here is a summary of the pros and cons of each approach.
Advantages for declaring loggers as static | Disadvantages for declaring loggers as static |
---|---|
|
|
Advantages for declaring loggers as instance variables | Disadvantages for declaring loggers as instance variables |
|
|
Static logger members cost a single variable reference for all instances of the class whereas an instance logger member will cost a variable reference for every instance of the class. For simple classes instantiated thousands of times there might be a noticeable difference.
However, more recent logging systems, e.g log4j or logback, support a distinct logger context for each application running in the application server. Thus, even if a single copy of log4j.jar or logback-classic.jar is deployed in the server, the logging system will be able to differentiate between applications and offer a distinct logging environment for each application.
More specifically, each time a logger is retrieved by invoking LoggerFactory.getLogger()
method, the underlying logging system will return an instance appropriate for the current application. Please note that within the same application retrieving a logger by a given name will always return the same logger. For a given name, a different logger will be returned only for different applications.
If the logger is static, then it will only be retrieved once when the hosting class is loaded into memory. If the hosting class is used in only in one application, there is not much to be concerned about. However, if the hosting class is shared between several applications, then all instances of the shared class will log into the context of the application which happened to first load the shared class into memory - hardly the behavior expected by the user.
Unfortunately, for non-native implementations of the SLF4J API, namely with slf4j-log4j12, log4j's repository selector will not be able to do its job properly because slf4j-log4j12, a non-native SLF4J binding, will store logger instances in a map, short-circuiting context-dependent logger retrieval. For native SLF4J implementations, such as logback-classic, repository selectors will work as expected.
The Apache Commons wiki contains an informative article covering the same question.
Logger serialization
Contrary to static variables, instance variables are serialized by default. As of SLF4J version 1.5.3, logger instances survive serialization. Thus, serialization of the host class no longer requires any special action, even when loggers are declared as instance variables. In previous versions, logger instances needed to be declared as transient
in the host class.
Summary
In summary, declaring logger members as static variables requires less CPU time and have a slightly smaller memory footprint. On the other hand, declaring logger members as instance variables requires more CPU time and have a slightly higher memory overhead. However, instance variables make it possible to create a distinct logger environment for each application, even for loggers declared in shared libraries. Perhaps more important than previously mentioned considerations, instance variables are IOC-friendly whereas static variables are not.
See also related discussion in the commons-logging wiki.
The following is the recommended logger declaration idiom. For reasons explained above, it is left to the user to determine whether loggers are declared as static variables or not.
package some.package;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final (static) Logger logger = LoggerFactory.getLogger(MyClass.class);
... etc
}
Unfortunately, give that the name of the hosting class is part of the logger declaration, the above logger declaration idiom is not is not resistant to cut-and-pasting between classes.
联系客服