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.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Why Log4j2 Beats Logback and Log4j1: Performance, Configuration, and Advanced Features

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.AsyncLoggerContextSelector

Conclusion

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceConfigurationlog4j2Lazy Evaluationjava loggingasync logging
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.