Log4j (1.x version)
Log4j 1.x, released by the Apache Foundation in 1999, has long been the cornerstone of Java logging. Its simple yet powerful Logger–Appender–Layout model set the standard for almost every subsequent framework, including Logback and Log4j 2. Although the 1.x line reached end‑of‑life in August 2015, many legacy applications still rely on it, making a solid understanding of its inner workings valuable for maintenance and migration efforts.
Core Architecture
The framework is built around three primary building blocks:
- Logger – The entry point for generating log events. Loggers are organized in a hierarchical tree, with the root logger named
rootLogger. Child loggers inherit the level and appenders of their parent unless explicitly overridden. - Appender – Determines where a log event is sent: console, file, database, network, etc. Common implementations include
ConsoleAppender,FileAppender,RollingFileAppender, andDailyRollingFileAppender. - Layout – Formats the raw log event into a human‑readable string.
PatternLayoutis the most widely used layout, allowing fine‑grained control over the output format through a pattern string.
Log Levels
Log4j 1.x defines five standard severity levels, ordered from least to most critical:
| Level | Typical Use |
|---|---|
| DEBUG | Detailed information for developers |
| INFO | General operational messages |
| WARN | Indicators of potential problems |
| ERROR | Errors that do not halt the application |
| FATAL | Severe failures that may terminate the application |
Only messages at or above the configured level are emitted. For example, setting the level to WARN automatically suppresses DEBUG and INFO logs.
Configuration
Two configuration formats are supported: log4j.properties and log4j.xml. Both are normally placed at the root of the classpath. A typical properties file looks like this:
# Root logger: INFO level, outputs to console and file
log4j.rootLogger=INFO, console, file
# Console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p] %c - %m%n
# Rolling file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/app.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d [%p] %c{1} - %m%n
Common PatternLayout Placeholders
| Placeholder | Meaning |
|---|---|
%d |
Date/time (format can be specified) |
%p |
Log level |
%c |
Logger name |
%m |
Log message |
%t |
Thread name |
%n |
Newline |
Sample Code
Add the dependency to your Maven project:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
A minimal Java example:
import org.apache.log4j.Logger;
public class Demo {
private static final Logger logger = Logger.getLogger(Demo.class);
public static void main(String[] args) {
logger.debug("Debugging details");
logger.info("Application started successfully");
logger.warn("Low disk space");
logger.error("Database connection failed", new RuntimeException("Timeout"));
}
}
Running this with the configuration above will produce console output similar to:
2024-05-20 10:30:00 [INFO ] Demo - Application started successfully
Practical Tips
End‑of‑life awareness – Log4j 1.x stopped receiving security patches in 2015. Known vulnerabilities, such as the CVE‑2019‑17571
SocketServerdeserialization flaw, still pose risks. Production systems should plan an upgrade.Performance hygiene – Avoid unnecessary string concatenation. Wrap expensive operations in a level check:
if (logger.isDebugEnabled()) { logger.debug("Result: " + computeExpensiveValue()); }Migration path – New projects should use Logback or Log4j 2. Both offer better performance, richer features, and configuration syntax that closely resembles Log4j 1.x, easing the transition.
Conclusion
Log4j 1.x’s elegant three‑layer design—Logger for event creation and filtering, Appender for destination routing, and Layout for formatting—laid the groundwork for modern Java logging. While the framework itself is no longer maintained, its concepts persist in contemporary libraries. Understanding its architecture, levels, and configuration not only aids in maintaining legacy code but also provides a solid foundation for adopting newer, more secure logging solutions.