Why Log4j2 Beats Logback and Log4j1: Performance, Configuration, and Advanced Features
This article compares Log4j2 with older Java logging frameworks, highlighting its superior asynchronous performance, zero‑GC design, flexible parameter formatting, simplified configuration options, and practical usage examples, ultimately showing why it should replace Logback and Log4j1 in modern applications.
Log4j2 Overview
Apache Log4j 2 is the successor to Log4j 1, offering major improvements over both Log4j 1 and Logback, including simplified configuration, powerful parameter formatting, and the best asynchronous performance among Java logging frameworks.
Simplified configuration
Advanced parameter formatting
Outstanding asynchronous performance
Log4j 2 consists of two modules: log4j-api (the façade, similar to SLF4J) and log4j-core (the implementation).
org.apache.logging.log4j:log4j-api
org.apache.logging.log4j:log4j-core
Top‑Tier Performance
Asynchronous Logging
Official benchmarks show that Log4j 2’s fully asynchronous mode delivers throughput of over 1.8 million events per second on a 64‑thread test, far surpassing Logback and Log4j 1, which stay below 200 k events per second.
Log4j 2 also supports a zero‑GC mode (default since version 2.6) that reuses message objects, string arrays, and byte arrays to avoid unnecessary object allocation.
Zero‑GC Design
All message‑related objects are reused, eliminating garbage collection caused by logging.
High‑Performance I/O
Log4j 2 provides a MemoryMappedFileAppender that uses memory‑mapped files for extremely fast I/O, though it requires a solid understanding of MemoryMappedFile before use.
Advanced Parameter Formatting
The API module supports richer formatting than SLF4J:
Standard {} placeholder formatting.
String.format‑style placeholders. logger.printf method for direct String.format usage.
Example of {} placeholder:
logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());String.format style example:
public static Logger logger = LogManager.getFormatterLogger("Foo");
logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);Note: To use the String.format style, obtain the logger via LogManager.getFormatterLogger instead of LogManager.getLogger .
Lazy Logging (Supplier + Lambda)
Log4j 2’s logger methods accept Supplier<?> arguments, enabling lazy evaluation of log messages and avoiding unnecessary computation when the log level is disabled.
void debug(String message, Supplier<?>... paramSuppliers);
void info(String message, Supplier<?>... paramSuppliers);
void trace(String message, Supplier<?>... paramSuppliers);
void error(String message, Supplier<?>... paramSuppliers);
// Example
logger.debug("Request payload: {}", () -> JSON.toJSONString(policyDTO));Simplified Configuration
Log4j 2 supports XML, JSON, YAML, and Properties configuration files, with XML being the most common.
Comparison of Logback and Log4j 2 XML configurations (same functionality):
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archives/app-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxFileSize>1 GB</maxFileSize>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="File"/>
</root>
</configuration>log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" status="warn" name="XInclude">
<Appenders>
<RollingFile name="File" fileName="logs/app.log" filePattern="logs/archives/app-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40c{1.} : %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="1 GB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>In Log4j 2 the appender element name itself acts as the tag, making the syntax more concise.
Integration with Other Logging Facades
Because Log4j 2 separates API and implementation, it can be adapted to other logging abstractions (e.g., SLF4J) when needed.
Other Notable Features
Asynchronous queue uses high‑performance LMAX Disruptor.
Rich set of appenders: JMS, JPA, Kafka, HTTP, MongoDB, CouchDB, Socket, Script, etc.
Support for custom log levels.
Basic Usage
Maven Dependency
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>Configuration File
Place log4j2.xml (or JSON/YAML) on the classpath, typically under src/main/resources.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" status="warn" name="XInclude">
<Properties>
<Property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40c{1.} : %m%n"/>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${PATTERN}"/>
</Console>
<RollingFile name="File" fileName="logs/app.log" filePattern="logs/archives/app-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="1 GB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="your.logger.package.name" level="debug" additivity="false"/>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>Creating a Logger
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Logger logger = LogManager.getLogger(MyClass.class);
logger.error(...);
logger.warn(...);
logger.info(...);
logger.debug(...);
logger.trace(...);If you prefer SLF4J, ensure proper adapter configuration; otherwise, using Log4j 2’s native API provides full feature access.
All‑Async Configuration (Important)
Enable full asynchronous logging by adding the following JVM option:
-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelectorConclusion
Log4j 2 currently offers the best performance, richest feature set, and active maintenance among Java logging frameworks, making it the recommended replacement for Logback and Log4j 1 in new and existing projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
