Java – log4j 2 configuration monitoring and bit by bit comparison
A colleague pointed out the following fragments of log4j 2.3 Code:
/** * Called to determine if the configuration has changed. */ @Override public void checkConfiguration() { final long current = System.currentTimeMillis(); if (((counter.incrementAndGet() & MASK) == 0) && (current >= nextCheck)) { LOCK.lock(); try { nextCheck = current + intervalSeconds; if (file.lastModified() > lastModified) { lastModified = file.lastModified(); for (final ConfigurationListener listener : listeners) { final Thread thread = new Thread(new ReconfigurationWorker(listener,reconfigurable)); thread.setDaemon(true); thread.start(); } } } finally { LOCK.unlock(); } }
Where counter is the atomicinteger field, mask is set to 0x0f and nextcheck is long
As far as I know, this method checks whether to reload the configuration, but only if the value of the counter can be divided by 16 and the next configuration check cycle is out of date
Why is this bitwise and there?
Since incrementandget is synchronous for counter instances, can it be considered a "cheap" restriction mechanism? Or maybe checkconfiguration is called more than necessary during a "typical" nextcheck cycle, so bitwise and is used as a performance trick (again, limit?)
Solution
Yes, it's a restriction mechanism In log4j 2.3, this method is called for each log event Bitwise and indicates that the rest of the check is performed only once every 16 log events
As the review points out, how effective this is in terms of performance improvement The call to system:: currenttimemillis is not free, and the performance of atomiclong:: incrementandget is degrades under extreme contention
Since the above codes of log4j 2.5 no longer exist (see log4j2-89) It has been replaced by the watchmanager class, which monitors whether the configuration file has been modified in the background thread