Back to Glossary
By 
September 15, 2026

What Is Log4j/Log4j2?

Log4j is an open-source logging framework for Java that applications use to record events while they run, maintained by the Apache Software Foundation as part of its Logging Services project. Log4j 2, often written as Log4j2, is the current major version and a complete rewrite of the original library.

Log4j is the library, while Log4Shell was the name given to a 2021 vulnerability found in it, and the two are not interchangeable. Log4j 1 and Log4j 2 are also separate codebases rather than successive versions of one, which is why advice about either frequently does not apply to the other.

What a Logging Framework Does

A logging framework turns scattered print statements into something an operator can control at runtime, without touching the application binary.

Loggers are named channels that code writes to, usually declared one per class. Levels rank messages by importance, from trace and debug through info, warn, error, and fatal, so output volume can be tuned at deployment rather than at compile time. Appenders decide where output goes: a file, a console, a socket, a database, a message queue. Layouts decide what it looks like on arrival, whether plain text for a human or JSON for a log pipeline.

Configuration binds these together in a file outside the source, which is what allows the log level on a single component to be raised during an incident and lowered afterward.

Log4j 1, Log4j 2, and Log4j 3

Log4j 1 dates to 1999 and became a default across enterprise Java. Apache's 1.x site was last published on 13 May 2012 at version 1.2.17, which remains its final release.

On 5 August 2015, the Logging Services Project Management Committee declared Log4j 1 end-of-life. Asked to revisit that call during the Log4Shell response, the committee reconfirmed it, stating that no resources would go into the codebase and that pull requests against it would be closed unfixed. Apache's Log4j 1 page consequently lists six vulnerabilities that will never be fixed. They include CVE-2019-17571, a SocketServer deserialization flaw that NVD scores at 9.8, a SQL injection weakness in the JDBCAppender, and two JNDI deserialization issues in JMSAppender and JMSSink. Organizations that cannot migrate sometimes adopt reload4j, an independently maintained drop-in replacement.

Log4j 2 arrived in 2014 with a plugin architecture and asynchronous logging built on a lock-free ring buffer; garbage-free operation in steady state followed in the 2.6 line. Apache maintains the 2.x line today, and its security advisories already reference 3.0.0 beta releases of a third major version.

Migration is less daunting than its reputation. Log4j 2 reads Log4j 1 configuration files, and Apache's position is that most applications using Log4j 1 can swap the 1.x jar for Log4j 2 jars and run. Security is not the only reason to move: Apache also documents that Log4j 1.2's MDC stopped working correctly on Java 9, when the version detection algorithm its code relied on changed.

The API and Core Split

The log4j-api artifact is the interface that application code compiles against, while log4j-core is the implementation doing the work: configuration parsing, appenders, layouts, and the lookup mechanism. An application can depend on the API and bind to a different implementation entirely at deployment.

Exposure follows the same division, because most Log4j vulnerabilities have been found in log4j-core, leaving applications that carry only log4j-api unaffected by them.

Log4j, SLF4J, and Logback

SLF4J is a facade with no logging implementation of its own; code writes to the SLF4J API and a binding routes those calls to whatever framework is present. Logback is an implementation, written by the original author of Log4j 1 and commonly paired with SLF4J. Log4j 2 is unusual in offering both an API and an implementation, plus bridges that let it sit behind SLF4J or accept calls written for Log4j 1.

An application can therefore contain several of these at once, with bridges routing between them. Establishing which implementation handles a given log call in practice is a prerequisite for knowing what is vulnerable.

Why Log4j Is Hard to Inventory?

Log4j is rarely a deliberate choice, arriving instead as a transitive dependency of a web framework, a database driver, or a monitoring agent, several levels below anything a developer selected.

Build habits make it harder still to find. Fat JARs bundle dependencies into a single archive where version metadata is not obvious. Shading relocates and renames packages, so a scanner looking for org.apache.logging.log4j may not find a copy that has been rewritten. And vendor appliances ship Java runtimes whose contents the operator never sees.

That depth is also what makes logging libraries an attractive target for malicious code in a supply chain attack. A logging call sits on the path of nearly every transaction an application handles, so code introduced there executes constantly and with the application's full privileges.

How Apache Handles Log4j Security Now

Apache publishes a threat model that states which inputs it treats as trusted, which adversary capabilities are in scope, and which reported behaviors it will decline as out of scope. Vulnerability reports are accepted through a bug bounty program that the Sovereign Tech Agency funds and YesWeHack hosts. Many project releases ship with a CycloneDX software bill of materials, linked to a machine-readable vulnerability disclosure report the project maintains centrally.

Recent advisories reflect the maturity of what they describe. Log4j CVEs published across 2025 and 2026 concern malformed JSON and XML output that downstream systems reject, missing TLS hostname verification in network appenders, and log injection through configuration attributes that were silently renamed. These are log integrity and transport security defects in the medium range, not remote code execution.

Raven Runtime Prevention analyzes how code behaves inside the running application and stops malicious execution in real time, including code that arrived through a dependency nobody selected directly. See how it works at Runtime Prevention.

Share this post