160

In Java, why is it best practice to declare a logger static final?

private static final Logger S_LOGGER
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user489041
  • 27,916
  • 55
  • 135
  • 204

14 Answers14

232
  • private - so that no other class can hijack your logger
  • static - so there is only one logger instance per class, also avoiding attempts to serialize loggers
  • final - no need to change the logger over the lifetime of the class

Also, I prefer name log to be as simple as possible, yet descriptive.

EDIT: However there is an interesting exception to these rules:

protected final Logger log = LoggerFactory.getLogger(getClass());

as opposed to:

private static final Logger log = LoggerFactory.getLogger(Foo.class);

The former way allows you to use the same logger name (name of the actual class) in all classes throughout the inheritance hierarchy. So if Bar extends Foo, both will log to Bar logger. Some find it more intuitive.

Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • 44
    if static and final then rather LOG (uppercase) – zacheusz Jul 11 '11 at 16:53
  • 51
    *@zacheusz*, I know, that's the point. Some follow Java naming convention religiously (nothing wrong with that), but I prefer easier to write and more pleasant to read `log` name rather than scattering the code with `LOG`. Just a matter of dev. team agreement. – Tomasz Nurkiewicz Jul 11 '11 at 16:56
  • 29
    Please note that it is no longer always recommended to declare loggers as static and final, see http://slf4j.org/faq.html#declared_static and http://wiki.apache.org/commons/Logging/FrequentlyAskedQuestions section Should I declare Log references static or not? – Matthew Farwell Oct 02 '11 at 10:06
  • 8
    @zacheusz Uppercased field name is used for constants. Logger isn't constant. [http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case](http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case) – michal.kreuzman Dec 17 '12 at 12:53
  • It's a matter of interpretation. So then what about static final String ? ;) I prefer the strict one. – zacheusz Dec 17 '12 at 16:33
  • 1
    A correction about the EDIT: If an attribute is declared to be used in the SubClasses, it canNOT be private but rather protected, otherwise the "children" won't have visibility to use it! – Carles Sala May 07 '13 at 14:25
  • 2
    @zacheusz not all static final attributes should be UPPERCASE: http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case – bsmk Mar 30 '14 at 20:20
  • I wouldnt use LoggerFactory.getLogger(getClass()) cause lots of times the class is proxyfied by spring so I get funny logs :) – sashok_bg Mar 14 '17 at 17:06
  • You can make the logger `transient` to make it non-serializable – alexyorke Apr 04 '17 at 03:42
  • @TomaszNurkiewicz do you think that making `protected` logger is a good idea all the time? Consider the case, when you're creating `abstract` class with `protected` logger. It means you're making the user of your class to use your logging system (or simply occupies the name of logger property for the class). I would suggest to make logger `private` all the time as it is just class-specific. – rilaby Jul 14 '17 at 09:41
  • LOGGER would be accurate grammatically. – Gabriel.ge Jun 11 '18 at 06:56
  • Besides this, I would put a new item, the security. See https://www.owasp.org/index.php/Poor_Logging_Practice – Altieres de Matos Jul 11 '18 at 20:12
  • 1
    @AltieresdeMatos, the OWASP page is incomplete; it does not mention at all whether or how a non-`static` logger can affect security. – Marcono1234 Mar 06 '21 at 17:26
  • @Marcono1234 Sure it gives a "reason"! It's not "good practice"! If you say it's good or bad "practice", you're not required to give a real reason! – Manius Feb 27 '23 at 07:43
  • @Manius, not sure if your comment is a joke or a wordplay; obviously you are never _required_ to give a reason but without giving the rationale for a certain practice it becomes incomprehensible and unhelpful. In the context of OWASP, OWASP is dedicated to _security_ and the page linked above even moved to a URL path containing `/vulnerabilities/`, so it should definitely explain more in detail what security aspects there are. – Marcono1234 Mar 04 '23 at 14:50
  • @Marcono1234 Haha Don't worry - was just a joke about how people love to say such and such is a good or bad practice, but often never give any reason or rationale. So we are in full agreement! It should explain further. – Manius Mar 04 '23 at 16:27
15

Check this blog post: Get Rid of Java Static Loggers. This is how you use slf4j with jcabi-log:

import com.jcabi.log.Logger;
class Foo {
  void save(File f) {
    Logger.info(this, "file %s saved successfully", f);
  }
}

And never use that static noise any more.

yegor256
  • 102,010
  • 123
  • 446
  • 597
  • 1
    An interesting alternative and definitely cleaner. I wonder how this scales compared to individual class loggers. – Ross May 21 '15 at 05:58
  • 16
    Write longer Logger.. (this, ...) each time. Nah. – Mikhail Boyarsky Sep 08 '15 at 15:05
  • The first comment in the related blog post indicates the evil side of the static methods :) So using private final Logger is the best practice I guess. – Bahadir Tasdemir Feb 26 '20 at 06:52
  • 1
    Slows logging calls down by a call to LoggerFactory.getLogger for each call to Logger.info and friends. Not an issue for most log levels, but if you have Logger.trace and a really huge amount of logging calls, this can have a performance impact, and most logging frameworks are really, really, really careful to make the do-not-log path as fast as humanly possible. I.e. jcabi-log impedes the "high-performance" aspect of high-performance loggers. – toolforger Jun 17 '22 at 18:33
12

static means that you only create one Logger per class, not one logger per instance of your class. Generally, this is what you want - as the loggers tend to vary solely based on class.

final means that you're not going to change the value of the logger variable. Which is true, since you almost always throw all log messages (from one class) to the same logger. Even on the rare occasions where a class might want to send some messages to a different logger, it would be much clearer to create another logger variable (e.g. widgetDetailLogger) rather than by mutating the value of a static variable on the fly.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
6

When would you want to change the value of the field?

If you're never going to change the value, making the field final makes it obvious that you'll never change the value.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    In many-many cases it IS obvious without adding the word final, which it this case becomes a kind of junk. – Dima Oct 26 '15 at 18:28
  • 7
    @Dima: Well I'm still grateful that the compiler will still throw an error if I *do* accidentally try to change the value in these cases... – Jon Skeet Oct 26 '15 at 19:44
3

Normally you initialize the logger to log using the class name -- which means that if they weren't static, you would end up with each instance of the class having an instance of it (high memory footprint), but all of these loggers would share the same configuration and behave exactly the same. That's the reason behind the static bit. Also because each Logger is initialised with the class name, to prevent conflicts with subclasses, you declare it private so it cannot be inherited. The final comes from the point that you normally don't change the Logger during the execution -- so once initialized you never "re-configured" it -- in which case it makes sense to make it final to ensure no one can change it (by mistake or otherwise). Of course if you are going to use a Logger in a different way you might need NOT to use static final -- but I would venture to guess 80% of apps would use logging as explained above.

Liv
  • 6,006
  • 1
  • 22
  • 29
3

To answer that question, you should have asked yourself what "static" and "final" are for.

For a Logger, (I assume you talk about Log4J Logger class) you want a category per class. Which should lead to the fact that you assign it only once, and there is no need for more than one instance per class. And presumably there is no reason to expose the Logger object of one class to another, so why dont make it private and follow some OO-Principles.

Also you should note, that the compiler is able to take benefits of that. So your code performs a bit better :)

2

This code is vulnerable,but, after Java7, we can use Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); instead of static logger.

nkduqi
  • 31
  • 3
2

Because that is usually the kind of functionnality that can be shared accross all instances of your objects. It does not make much sense (90% of the time) to have a different logger for two instances of the same class.

However, you can also see sometimes logger classes declared as singletons or even simply offering static functions to log your stuff.

Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124
1

Ideally Logger should be as follows upto Java 7, for giving no Sonar and giving a Compliant Code: private: never be accessible outside of its parent class. If another class needs to log something, it should instantiate its own logger. static: not be dependent on an instance of a class (an object). When logging something, contextual information can of course be provided in the messages but the logger should be created at class level to prevent creating a logger along with each object and hence preventing High Memory footprint. final: be created once and only once per class.

1

According to the info I read on the internet about making the logger static or not, the best practice is to use it according to the use cases.

There are two main arguments:

  1. When you make it static, it is not garbage collected (memory usage & performance).

  2. When you don't make it static it is created for each class instance (memory usage)

Thus, When you are creating a logger for a singleton, you don't need to make it static. Because there will be only one instance thus one logger.

On the other hand, if you are creating a logger for a model or entity class, you should make it static not to create duplicated loggers.

Bahadir Tasdemir
  • 10,325
  • 4
  • 49
  • 61
1

In most cases, you are not going to change the reference and final modifier marks it. You don't need separate instances for each class instance - so static. And first of all this is for performance - it can be nicely optimized (final) and saves memory (static).

zacheusz
  • 8,750
  • 3
  • 36
  • 60
1

We use

private - so that it remains a private data member for the class (which we usually want for every class level variable).

static - this is important. We want a single logger instance for the entire class and not that every new instance/object of the class spawns a new logger. Static key word in java is made for the same. Hence we declare it static

final - we don't want to change the value of our logger variable, rather we want it to remain constant for the entire class lifecycle.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Akash Verma
  • 638
  • 1
  • 11
  • 15
0

In addition to the reasons given in the other answers one thing I ran into was that if my logger was neither static nor final:

...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);

public String toJson() {
  GsonBuilder gsonBuilder = new GsonBuilder();   
  return gsonBuilder.create().toJsonTree(this).toString();
}
...

in certain cases (when I was using the Gson library) I would get stackoverflow exception. My specific situation was to instantiate the class containing the non static non final logger. Then call the toJson method which invoked GsonBuilder:

...
DataSummary ds = new DataSummary(data);    
System.out.println(ds.toJson());
...
Paul
  • 7,155
  • 8
  • 41
  • 40
0

Actually static loggers can be "harmful" as they are supposed to work in a static context. When having a dynamic environment eg. OSGi it might help to use non-static loggers. As some logging implementations do a caching of loggers internally (AFAIK at least log4j) the performance impact might negligible.

One drawback of static loggers is eg. garbage collection (when a class is used only once eg. during initialization the logger will be still kept around).

For more details check:

See also:

ViToni
  • 882
  • 9
  • 12
  • Classes are typically garbage-collected, and their static fields with them. (This used to be different a few years ago, but things like PermGen should be gone unless you explicitly select a GC that has it AFAIR.) – toolforger Jun 17 '22 at 18:37