Is it efficient to get Logger from a static initializer of a final variable?

We have a lot of class code that has several templates, for example:

private static Logger logger = null; private static Logger getLogger() { if (logger == null) { logger = Logger.getLogger(MyClass.class); } return logger; } 

The idea is that a class can log debugging information in Logger. The first code that should register something calls getLogger (), and this leads to the creation of a logger.

There are a few things that I don't like about this template. At first, singleton getLogger () is not synchronized and not synchronized, but the correct one places a burden on each subsequent call for no reason.

I really want to be able to condensate this just before this:

 private static final Logger logger = Logger.getLogger(MyClass.class); 

Then I can just refer to the registrar directly and not even worry about how to generate a singleton.

The problem I'm afraid of is that by doing this I cause the Logger to be created when the class loads, even if the registrar is never called. I have 10,000 + odd classes all calling getLogger (), so how many Logger instances do I really create here? If my log4j properties contain multiple additives, am I just referring to the same log again and again, or am I creating 10,000 of these things?

+7
source share
6 answers

If you use the default Log4j configuration (that is, the default LoggerRepository, DefaultCategoryFactory, etc.), you will create 10,000 instances of Logger. How much memory do they consume? No one but God and your Profiler knows about it. (And I assume that only the latter will tell you about this).

If the memory size is too large for your environment, move the Logger initialization to a static inner class as follows:

 static class LoggerHolder { static Logger logger = Logger.getLogger(MyClass.class); } private static Logger getLogger() { return LoggerHolder.logger; } 

Thus, a Logger instance will only be created the first time getLogger called. (This method is known as Initialization on Demand (IODH), it is thread safe and has zero synchronization overhead).

And can I give you one offtopic suggestion? Try replacing Log4J with a combination of SLF4J + Logback . They are written by the same authors and described as " a successor to the popular log4j project, picking up where log4j leaves off ". You can read more in this SO thread .

+2
source

It will create objects only if the class is actually initialized, i.e. if used. At this point, do the small overheads of one object per class really matter?

The simple answer is: try in both directions and see if you can observe any significant differences in performance / memory / etc. I doubt that you can, but if you can, then you can decide, based on the data, what is the most suitable course of action.

+2
source

You create a separate log instance for each class you load, however I believe that they have a small amount of memory. Log4J is known to be optimized, and I doubt they thought about memory usage.

In general, if you have 10K different classes, your application is huge - I doubt that you will notice a significant difference in memory consumption. But the best thing, of course, is to measure it in both directions, in your specific environment.

+1
source

Static variables initialized once and the same object are used for all instances. You do not need this private static Logger getLogger() method for a singleton template.

Just make him lazy, but don’t think it’s a big win. Thounsands of objects are created and destroyed in a very small amount of time.

0
source

What you want (static end field) is what is usually done, and PMD is recommended. If you have a logger, there is a good chance it used, so initializing it lazily will not bring anything in terms of memory and, of course, does not greatly affect performance.

I would use its LOGGER , since it is a constant.

0
source

The OP unsynchronized getLogger() method is fine; ince Logger is thread safe. (I hope, since Logger is modified and intended for simultaneous use, I will be surprised if its link cannot be published without additional synchronization.)

Sometimes creating 2 registrars for the same class is also not a problem.

However, the problem of memory usage is not needed. The presence of an additional object for each class should not be associated with overhead (I hope the Logger object is not too large)

0
source

All Articles