0
# SLF4J JDK14 Provider
1
2
SLF4J JDK14 Provider is a binding implementation that bridges the SLF4J (Simple Logging Facade for Java) API with Java Util Logging (JUL), the built-in logging framework in the JDK. This lightweight adapter enables SLF4J-based applications to output logs through the standard java.util.logging framework without requiring additional logging dependencies.
3
4
## Package Information
5
6
- **Package Name**: org.slf4j:slf4j-jdk14
7
- **Package Type**: maven
8
- **Language**: Java
9
- **Installation**: Add to Maven dependencies or use as a service provider jar
10
11
**Maven Dependency**:
12
```xml
13
<dependency>
14
<groupId>org.slf4j</groupId>
15
<artifactId>slf4j-jdk14</artifactId>
16
<version>2.0.17</version>
17
</dependency>
18
```
19
20
## Core Imports
21
22
```java
23
import org.slf4j.jul.JULServiceProvider;
24
import org.slf4j.jul.JDK14LoggerFactory;
25
import org.slf4j.jul.JDK14LoggerAdapter;
26
```
27
28
## Basic Usage
29
30
The slf4j-jdk14 provider is automatically discovered via Java's ServiceLoader mechanism when present on the classpath. No explicit configuration is required for basic usage:
31
32
```java
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35
36
public class Example {
37
private static final Logger logger = LoggerFactory.getLogger(Example.class);
38
39
public void demonstrateLogging() {
40
logger.trace("Trace level message");
41
logger.debug("Debug level message");
42
logger.info("Info level message");
43
logger.warn("Warning level message");
44
logger.error("Error level message", new RuntimeException("Example error"));
45
}
46
}
47
```
48
49
## Architecture
50
51
The provider consists of three main components:
52
53
- **JULServiceProvider**: Service provider implementation for automatic discovery
54
- **JDK14LoggerFactory**: Factory for creating and caching logger instances
55
- **JDK14LoggerAdapter**: Adapter that wraps java.util.logging.Logger instances
56
57
**Level Mapping**: SLF4J levels are mapped to JUL levels:
58
- TRACE → Level.FINEST
59
- DEBUG → Level.FINE
60
- INFO → Level.INFO
61
- WARN → Level.WARNING
62
- ERROR → Level.SEVERE
63
64
## Capabilities
65
66
### Service Provider Implementation
67
68
The main service provider that enables automatic SLF4J integration.
69
70
```java { .api }
71
public class JULServiceProvider implements SLF4JServiceProvider {
72
// API version this implementation is compiled against
73
public static String REQUESTED_API_VERSION = "2.0.99";
74
75
public JULServiceProvider();
76
public ILoggerFactory getLoggerFactory();
77
public IMarkerFactory getMarkerFactory();
78
public MDCAdapter getMDCAdapter();
79
public String getRequestedApiVersion();
80
public void initialize();
81
}
82
```
83
84
**Usage**:
85
This class is automatically instantiated by SLF4J's ServiceLoader mechanism. Manual instantiation is not typically needed.
86
87
### Logger Factory
88
89
Factory implementation that creates and manages logger instances.
90
91
```java { .api }
92
public class JDK14LoggerFactory implements ILoggerFactory {
93
public JDK14LoggerFactory();
94
public Logger getLogger(String name);
95
}
96
```
97
98
**Usage**:
99
```java
100
JDK14LoggerFactory factory = new JDK14LoggerFactory();
101
Logger logger = factory.getLogger("com.example.MyClass");
102
```
103
104
### Logger Adapter
105
106
Logger adapter that bridges SLF4J Logger interface to java.util.logging.Logger.
107
108
```java { .api }
109
public final class JDK14LoggerAdapter extends LegacyAbstractLogger
110
implements LocationAwareLogger {
111
112
// Constants for stack trace analysis
113
static final int MAX_SEARCH_DEPTH = 12;
114
static String SELF = JDK14LoggerAdapter.class.getName();
115
static String[] BARRIER_CLASSES;
116
117
// Constructor
118
JDK14LoggerAdapter(java.util.logging.Logger logger);
119
120
// Level check methods
121
public boolean isTraceEnabled();
122
public boolean isDebugEnabled();
123
public boolean isInfoEnabled();
124
public boolean isWarnEnabled();
125
public boolean isErrorEnabled();
126
127
// Logging methods (inherited from parent classes)
128
// All standard SLF4J Logger interface methods available
129
130
// LocationAwareLogger method
131
public void log(Marker marker, String callerFQCN, int slf4jLevelInt,
132
String message, Object[] arguments, Throwable throwable);
133
134
// LoggingEvent support
135
public void log(LoggingEvent event);
136
137
// Level conversion utilities
138
private static Level slf4jLevelToJULLevel(org.slf4j.event.Level slf4jLevel);
139
private static Level slf4jLevelIntToJULLevel(int levelInt);
140
141
// Event processing
142
private LogRecord eventToRecord(LoggingEvent event, Level julLevel);
143
}
144
```
145
146
**Usage**:
147
Logger instances are typically obtained through SLF4J's LoggerFactory, not directly instantiated:
148
149
```java
150
Logger logger = LoggerFactory.getLogger(MyClass.class);
151
152
// Level checks
153
if (logger.isDebugEnabled()) {
154
logger.debug("Debug message with parameter: {}", value);
155
}
156
157
// Direct logging
158
logger.info("Application started");
159
logger.warn("Configuration missing, using defaults");
160
logger.error("Failed to process request", exception);
161
162
// LoggingEvent support (typically used by SLF4J internally)
163
LoggingEvent event = new LoggingEvent(Level.INFO, logger);
164
event.setMessage("Event-based logging");
165
logger.log(event);
166
```
167
168
### Level Check Operations
169
170
All logger adapters provide level checking methods for performance optimization.
171
172
```java { .api }
173
// Check if specific logging levels are enabled
174
boolean isTraceEnabled();
175
boolean isDebugEnabled();
176
boolean isInfoEnabled();
177
boolean isWarnEnabled();
178
boolean isErrorEnabled();
179
```
180
181
**Usage**:
182
```java
183
// Avoid expensive string operations when level is disabled
184
if (logger.isDebugEnabled()) {
185
logger.debug("Processing item: {}", expensiveToString(item));
186
}
187
```
188
189
### Level Conversion
190
191
The provider includes utility methods for converting SLF4J levels to JUL levels.
192
193
```java { .api }
194
// Internal level conversion methods
195
private static Level slf4jLevelToJULLevel(org.slf4j.event.Level slf4jLevel);
196
private static Level slf4jLevelIntToJULLevel(int levelInt);
197
```
198
199
**Level Mapping**:
200
- `TRACE` → `Level.FINEST`
201
- `DEBUG` → `Level.FINE`
202
- `INFO` → `Level.INFO`
203
- `WARN` → `Level.WARNING`
204
- `ERROR` → `Level.SEVERE`
205
206
### Stack Trace Analysis
207
208
The adapter preserves caller information through stack trace analysis with configurable depth limits.
209
210
```java { .api }
211
// Stack trace analysis constants
212
static final int MAX_SEARCH_DEPTH = 12;
213
static String SELF = "org.slf4j.jul.JDK14LoggerAdapter";
214
static String[] BARRIER_CLASSES; // Contains known SLF4J framework classes
215
```
216
217
**Caller Detection**:
218
The adapter analyzes up to 12 stack frames to identify the actual calling class and method, filtering out known SLF4J framework classes to provide accurate source location information in log records.
219
220
### LoggingEvent Processing
221
222
The adapter supports SLF4J's LoggingEvent API for structured logging scenarios.
223
224
```java { .api }
225
// LoggingEvent processing
226
public void log(LoggingEvent event);
227
private LogRecord eventToRecord(LoggingEvent event, Level julLevel);
228
```
229
230
**LoggingEvent Usage**:
231
```java
232
// Create and configure a logging event
233
LoggingEvent event = new LoggingEvent();
234
event.setLevel(Level.INFO);
235
event.setLoggerName("com.example.MyClass");
236
event.setMessage("Processing completed for user: {}");
237
event.setArgumentArray(new Object[]{"john.doe"});
238
event.setTimeStamp(System.currentTimeMillis());
239
240
// Log through the adapter
241
logger.log(event);
242
```
243
244
**Event to Record Conversion**:
245
The `eventToRecord` method converts SLF4J LoggingEvent objects to JUL LogRecord objects, handling:
246
- Message formatting with parameters
247
- Timestamp preservation
248
- Logger name mapping
249
- Exception handling
250
- Source location information
251
252
### Service Provider Configuration
253
254
The provider is automatically discovered through Java's ServiceLoader mechanism via the configuration file:
255
256
**File Structure**:
257
```
258
src/main/resources/
259
└── META-INF/
260
└── services/
261
└── org.slf4j.spi.SLF4JServiceProvider
262
```
263
264
**File Content**: `org.slf4j.jul.JULServiceProvider`
265
266
This configuration enables automatic discovery of the JUL provider when slf4j-jdk14 is present on the classpath.
267
268
### Module System Integration
269
270
For Java 9+ module system:
271
272
```java { .api }
273
module org.slf4j.jul {
274
requires org.slf4j;
275
requires java.logging;
276
277
exports org.slf4j.jul;
278
opens org.slf4j.jul to org.slf4j;
279
280
provides org.slf4j.spi.SLF4JServiceProvider
281
with org.slf4j.jul.JULServiceProvider;
282
}
283
```
284
285
## Types
286
287
### Core SLF4J Types
288
289
These types are provided by the SLF4J API dependency:
290
291
```java { .api }
292
// From org.slf4j.spi
293
interface SLF4JServiceProvider {
294
ILoggerFactory getLoggerFactory();
295
IMarkerFactory getMarkerFactory();
296
MDCAdapter getMDCAdapter();
297
String getRequestedApiVersion();
298
void initialize();
299
}
300
301
interface ILoggerFactory {
302
Logger getLogger(String name);
303
}
304
305
interface LocationAwareLogger extends Logger {
306
void log(Marker marker, String fqcn, int level, String message,
307
Object[] argArray, Throwable t);
308
}
309
310
// From org.slf4j
311
interface Logger {
312
// Standard logging methods
313
void trace(String msg);
314
void debug(String msg);
315
void info(String msg);
316
void warn(String msg);
317
void error(String msg);
318
319
// Parameterized logging methods
320
void trace(String format, Object... arguments);
321
void debug(String format, Object... arguments);
322
void info(String format, Object... arguments);
323
void warn(String format, Object... arguments);
324
void error(String format, Object... arguments);
325
326
// Exception logging methods
327
void trace(String msg, Throwable t);
328
void debug(String msg, Throwable t);
329
void info(String msg, Throwable t);
330
void warn(String msg, Throwable t);
331
void error(String msg, Throwable t);
332
333
// Level check methods
334
boolean isTraceEnabled();
335
boolean isDebugEnabled();
336
boolean isInfoEnabled();
337
boolean isWarnEnabled();
338
boolean isErrorEnabled();
339
}
340
341
interface Marker {
342
String getName();
343
void add(Marker reference);
344
boolean remove(Marker reference);
345
boolean contains(Marker other);
346
boolean contains(String name);
347
}
348
349
interface IMarkerFactory {
350
Marker getMarker(String name);
351
boolean exists(String name);
352
boolean detachMarker(String name);
353
}
354
355
interface MDCAdapter {
356
void put(String key, String val);
357
String get(String key);
358
void remove(String key);
359
void clear();
360
}
361
362
class LoggingEvent {
363
Level getLevel();
364
String getLoggerName();
365
String getMessage();
366
Object[] getArgumentArray();
367
Throwable getThrowable();
368
long getTimeStamp();
369
}
370
```
371
372
### Java Util Logging Types
373
374
Key JUL types used by the implementation:
375
376
```java { .api }
377
// From java.util.logging
378
class Logger {
379
static Logger getLogger(String name);
380
boolean isLoggable(Level level);
381
void log(LogRecord record);
382
String getName();
383
}
384
385
class LogRecord {
386
LogRecord(Level level, String msg);
387
void setLoggerName(String name);
388
void setThrown(Throwable ex);
389
void setSourceClassName(String sourceClassName);
390
void setSourceMethodName(String sourceMethodName);
391
void setMillis(long millis);
392
}
393
394
class Level {
395
static final Level FINEST;
396
static final Level FINE;
397
static final Level INFO;
398
static final Level WARNING;
399
static final Level SEVERE;
400
}
401
```
402
403
## Error Handling
404
405
The provider handles several error scenarios:
406
407
### Common Exceptions
408
409
- **IllegalStateException**: Thrown when an unrecognized SLF4J level is encountered during level mapping
410
- **IllegalArgumentException**: Thrown when both throwable argument and throwable in argument array are provided to logging methods
411
412
### Error Scenarios
413
414
1. **Unrecognized Level**: When `slf4jLevelToJULLevel` receives an unknown SLF4J level enum value
415
2. **Double Throwable**: When both explicit throwable parameter and throwable in arguments array are provided to LoggingEvent processing
416
3. **JUL Initialization Failure**: Handled gracefully during factory construction by calling `java.util.logging.Logger.getLogger("")`
417
4. **Stack Trace Analysis**: Limited to `MAX_SEARCH_DEPTH` (12) stack frames to prevent excessive performance overhead
418
5. **Event Processing**: In `eventToRecord`, throws IllegalArgumentException if both event throwable and formatted message throwable are present
419
420
## Configuration
421
422
### JUL Configuration
423
424
Since this provider delegates to java.util.logging, configure JUL using standard mechanisms:
425
426
**logging.properties**:
427
```properties
428
# Root logger level
429
.level = INFO
430
431
# Console handler
432
handlers = java.util.logging.ConsoleHandler
433
434
# Console handler level and format
435
java.util.logging.ConsoleHandler.level = ALL
436
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
437
438
# Package-specific levels
439
com.example.level = DEBUG
440
```
441
442
**Programmatic Configuration**:
443
```java
444
import java.util.logging.Logger;
445
import java.util.logging.Level;
446
import java.util.logging.ConsoleHandler;
447
448
Logger julLogger = Logger.getLogger("com.example");
449
julLogger.setLevel(Level.FINE);
450
julLogger.addHandler(new ConsoleHandler());
451
```
452
453
### Integration Notes
454
455
1. **Automatic Discovery**: No manual configuration needed when slf4j-jdk14 is on classpath
456
2. **Thread Safety**: Logger instances are cached in ConcurrentHashMap for thread-safe access
457
3. **Performance**: Level checks are delegated to JUL's isLoggable() for optimal performance
458
4. **Caller Information**: Stack trace analysis preserves caller location information in log records
459
5. **Root Logger Mapping**: SLF4J ROOT logger is properly mapped to JUL's "" (empty string) root logger