Skip to content

Commit 6e7e345

Browse files
committed
Merge branch 'feature/2.x/change-is-webapp' into 2.x
2 parents ecb99af + ce46f2e commit 6e7e345

File tree

19 files changed

+78
-57
lines changed

19 files changed

+78
-57
lines changed

log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,10 @@ public String getThreadContextMap() {
326326
return threadContextMapClass;
327327
}
328328
// Default based on properties
329-
if (Constants.ENABLE_THREADLOCALS) {
330-
return props.getBooleanProperty(GC_FREE_THREAD_CONTEXT_PROPERTY)
331-
? GC_FREE_THREAD_CONTEXT_PROPERTY
332-
: COPY_ON_WRITE_CONTEXT_MAP;
329+
if (props.getBooleanProperty(GC_FREE_THREAD_CONTEXT_PROPERTY)) {
330+
return GARBAGE_FREE_CONTEXT_MAP;
333331
}
334-
return WEB_APP_CONTEXT_MAP;
332+
return Constants.ENABLE_THREADLOCALS ? COPY_ON_WRITE_CONTEXT_MAP : WEB_APP_CONTEXT_MAP;
335333
}
336334

337335
/**

log4j-api/src/main/java/org/apache/logging/log4j/util/Constants.java

+30-7
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,54 @@
1616
*/
1717
package org.apache.logging.log4j.util;
1818

19+
import org.apache.logging.log4j.spi.Provider;
20+
1921
/**
2022
* Log4j API Constants.
2123
*
2224
* @since 2.6.2
2325
*/
2426
public final class Constants {
2527
/**
26-
* {@code true} if we think we are running in a web container, based on the boolean value of system property
27-
* "log4j2.is.webapp", or (if this system property is not set) whether the {@code javax.servlet.Servlet} class
28-
* is present in the classpath.
28+
* Specifies whether Log4j is used in a servlet container
29+
* <p>
30+
* If {@code true} Log4j disables the features, which are incompatible with a typical servlet application:
31+
* </p>
32+
* <ol>
33+
* <li>It disables the usage of {@link ThreadLocal}s for object pooling (unless the user has explicitly provided a {@link #ENABLE_THREADLOCALS} property)</li>
34+
* <li>It uses a web-application safe implementation of {@link org.apache.logging.log4j.spi.ThreadContextMap}
35+
* (see {@link Provider#getThreadContextMap()}),</li>
36+
* <li>It disables the shutdown hook,</li>
37+
* <li>It uses the caller thread to send JMX notifications.</li>
38+
* </ol>
39+
* <p>
40+
* The value of this constant depends upon the presence of the Servlet API on the classpath and can be
41+
* overridden using the {@code "log4j2.isWebapp"} system property.
42+
* </p>
2943
*/
3044
public static final boolean IS_WEB_APP = PropertiesUtil.getProperties()
3145
.getBooleanProperty(
3246
"log4j2.is.webapp",
3347
isClassAvailable("javax.servlet.Servlet") || isClassAvailable("jakarta.servlet.Servlet"));
3448

3549
/**
36-
* Kill switch for object pooling in ThreadLocals that enables much of the LOG4J2-1270 no-GC behaviour.
50+
* Specifies whether Log4j can bind non-JRE types to {@link ThreadLocal}s
51+
* <p>
52+
* The value of this constant is {@code true}, unless Log4j is running in a servlet container (cf.
53+
* {@link #IS_WEB_APP}). Use the {@code "log4j2.enableThreadlocals} system property to override its value.
54+
* </p>
55+
* <p>
56+
* In order to enable the garbage-free behavior described in
57+
* <a href="https://issues.apache.org/jira/browse/LOG4J2-1270">LOG4J2-1270</a>, this constant must be {@code
58+
* true}.
59+
* </p>
3760
* <p>
38-
* {@code True} for non-{@link #IS_WEB_APP web apps}, disable by setting system property
39-
* "log4j2.enable.threadlocals" to "false".
61+
* <strong>Warning:</strong> This setting does <strong>not</strong> disable all thread locals. It only
62+
* disables those thread locals that can cause a classloader memory leak.
4063
* </p>
4164
*/
4265
public static final boolean ENABLE_THREADLOCALS =
43-
!IS_WEB_APP && PropertiesUtil.getProperties().getBooleanProperty("log4j2.enable.threadlocals", true);
66+
PropertiesUtil.getProperties().getBooleanProperty("log4j2.enable.threadlocals", !IS_WEB_APP);
4467

4568
/**
4669
* Java major version.

log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/GcFreeLoggingTestUtil.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.logging.log4j.core.test;
1818

1919
import static org.assertj.core.api.Assertions.assertThat;
20-
import static org.junit.jupiter.api.Assertions.assertFalse;
2120
import static org.junit.jupiter.api.Assertions.assertTrue;
2221

2322
import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
@@ -47,15 +46,13 @@ public enum GcFreeLoggingTestUtil {
4746

4847
public static void executeLogging(final String configurationFile, final Class<?> testClass) throws Exception {
4948

50-
System.setProperty("log4j2.enable.threadlocals", "true");
51-
System.setProperty("log4j2.enable.direct.encoders", "true");
52-
System.setProperty("log4j2.is.webapp", "false");
53-
System.setProperty("log4j.configurationFile", configurationFile);
49+
System.setProperty("log4j2.enableThreadlocals", "true");
50+
System.setProperty("log4j2.enableDirectEncoders", "true");
51+
System.setProperty("log4j2.configurationFile", configurationFile);
5452
System.setProperty("log4j2.clock", "SystemMillisClock");
5553

5654
assertTrue(Constants.ENABLE_THREADLOCALS, "Constants.ENABLE_THREADLOCALS");
5755
assertTrue(Constants.ENABLE_DIRECT_ENCODERS, "Constants.ENABLE_DIRECT_ENCODERS");
58-
assertFalse(Constants.IS_WEB_APP, "Constants.IS_WEB_APP");
5956

6057
final MyCharSeq myCharSeq = new MyCharSeq();
6158
final Marker testGrandParent = MarkerManager.getMarker("testGrandParent");

log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ public class EventParameterMemoryLeakTest {
3939

4040
@BeforeAll
4141
public static void beforeClass() {
42-
System.setProperty("log4j2.enable.threadlocals", "true");
43-
System.setProperty("log4j2.enable.direct.encoders", "true");
44-
System.setProperty("log4j2.is.webapp", "false");
42+
System.setProperty("log4j2.enableThreadlocals", "true");
43+
System.setProperty("log4j2.enableDirectEncoders", "true");
4544
System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "EventParameterMemoryLeakTest.xml");
4645
}
4746

log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AbstractAsyncThreadContextTestBase.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ public abstract class AbstractAsyncThreadContextTestBase {
5959

6060
@BeforeAll
6161
public static void beforeClass() {
62-
props.setProperty("log4j2.is.webapp", false);
63-
props.setProperty("AsyncLogger.RingBufferSize", 128); // minimum ringbuffer size
64-
props.setProperty("AsyncLoggerConfig.RingBufferSize", 128); // minimum ringbuffer size
62+
props.setProperty("log4j2.enableThreadlocals", true);
63+
props.setProperty("log4j2.asyncLoggerRingBufferSize", 128); // minimum ringbuffer size
64+
props.setProperty("log4j2.asyncLoggerConfigRingBufferSize", 128); // minimum ringbuffer size
6565
}
6666

6767
protected enum Mode {

log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerArgumentFreedOnErrorTest.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,9 @@ public class AsyncLoggerArgumentFreedOnErrorTest {
3737

3838
@BeforeClass
3939
public static void beforeClass() {
40-
System.setProperty("log4j2.enable.threadlocals", "true");
41-
System.setProperty("log4j2.enable.direct.encoders", "true");
42-
System.setProperty("log4j2.is.webapp", "false");
43-
System.setProperty("log4j.format.msg.async", "true");
40+
System.setProperty("log4j2.enableThreadlocals", "true");
41+
System.setProperty("log4j2.enableDirectEncoders", "true");
42+
System.setProperty("log4j2.formatMsgAsync", "true");
4443
System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, AsyncLoggerContextSelector.class.getName());
4544
}
4645

log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigErrorOnFormat.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ public class AsyncLoggerConfigErrorOnFormat {
4242

4343
@BeforeClass
4444
public static void beforeClass() {
45-
System.setProperty("log4j2.is.webapp", "false");
45+
System.setProperty("log4j2.enableThreadlocals", "true");
4646
System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "AsyncLoggerConfigErrorOnFormat.xml");
4747
// Log4jLogEvent.toString invokes message.toString
4848
System.setProperty("log4j2.logEventFactory", DefaultLogEventFactory.class.getName());
4949
}
5050

5151
@AfterClass
5252
public static void afterClass() {
53-
System.clearProperty("log4j2.is.webapp");
53+
System.clearProperty("log4j2.enableThreadlocals");
5454
System.clearProperty("log4j2.logEventFactory");
5555
}
5656

log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigWithAsyncEnabledTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ public class AsyncLoggerConfigWithAsyncEnabledTest {
3838

3939
@BeforeClass
4040
public static void beforeClass() {
41-
System.setProperty("log4j2.is.webapp", "false");
42-
System.setProperty("Log4jContextSelector", AsyncLoggerContextSelector.class.getCanonicalName());
41+
System.setProperty("log4j2.enableThreadlocals", "true");
42+
System.setProperty("log4j2.contextSelector", AsyncLoggerContextSelector.class.getCanonicalName());
4343
// Reuse the configuration from AsyncLoggerConfigTest4
4444
System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "AsyncLoggerConfigTest4.xml");
4545
}
4646

4747
@AfterClass
4848
public static void afterClass() {
49-
System.clearProperty("log4j2.is.webapp");
50-
System.clearProperty("Log4jContextSelector");
49+
System.clearProperty("log4j2.enableThreadlocals");
50+
System.clearProperty("log4j2.contextSelector");
5151
}
5252

5353
@Test

log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/NestedLoggingFromThrowableMessageTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class NestedLoggingFromThrowableMessageTest {
4747
public static void beforeClass() {
4848
file1.delete();
4949
file2.delete();
50-
System.setProperty("log4j2.is.webapp", "false");
50+
System.setProperty("log4j2.enableThreadlocals", "true");
5151
}
5252

5353
@Rule

log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/DatePatternConverterWithThreadLocalsTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
import org.apache.logging.log4j.test.junit.SetTestProperty;
2020
import org.apache.logging.log4j.test.junit.UsingTestProperties;
2121

22-
@SetTestProperty(key = "log4j2.is.webapp", value = "false")
23-
@SetTestProperty(key = "log4j2.enable.threadlocals", value = "true")
22+
@SetTestProperty(key = "log4j2.enableThreadlocals", value = "true")
2423
@UsingTestProperties
2524
class DatePatternConverterWithThreadLocalsTest extends DatePatternConverterTestBase {
2625

log4j-core-test/src/test/java/org/apache/logging/log4j/core/util/ShutdownCallbackRegistryTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ public class ShutdownCallbackRegistryTest {
3939

4040
@BeforeAll
4141
public static void setUpClass() {
42-
System.setProperty("log4j2.is.webapp", "false");
42+
System.setProperty("log4j2.shutdownHookEnabled", "true");
4343
System.setProperty(ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY, Registry.class.getName());
4444
}
4545

4646
@AfterAll
4747
public static void afterClass() {
4848
System.clearProperty(ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY);
49-
System.clearProperty("log4j2.is.webapp");
49+
System.clearProperty("log4j2.shutdownHookEnabled");
5050
}
5151

5252
@Test

log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,8 @@
4646
public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallbackRegistry {
4747

4848
private static final StatusLogger LOGGER = StatusLogger.getLogger();
49-
private static final boolean SHUTDOWN_HOOK_ENABLED =
50-
PropertiesUtil.getProperties().getBooleanProperty(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED, true)
51-
&& !Constants.IS_WEB_APP;
49+
private static final boolean SHUTDOWN_HOOK_ENABLED = PropertiesUtil.getProperties()
50+
.getBooleanProperty(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED, !Constants.IS_WEB_APP);
5251

5352
private final ContextSelector selector;
5453
private final ShutdownCallbackRegistry shutdownCallbackRegistry;

log4j-core/src/main/java/org/apache/logging/log4j/core/util/Constants.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public final class Constants {
7777

7878
/**
7979
* {@code true} if we think we are running in a web container, based on the boolean value of system property
80-
* "log4j2.is.webapp", or (if this system property is not set) whether the {@code javax.servlet.Servlet} class
80+
* "log4j2.isWebapp", or (if this system property is not set) whether the {@code javax.servlet.Servlet} class
8181
* is present in the classpath.
8282
*/
8383
public static final boolean IS_WEB_APP = org.apache.logging.log4j.util.Constants.IS_WEB_APP;
@@ -97,9 +97,9 @@ public final class Constants {
9797
* {@link org.apache.logging.log4j.core.layout.ByteBufferDestination}s without creating intermediate temporary
9898
* Objects.
9999
* <p>
100-
* {@code True} by default iff all loggers are asynchronous because system property
101-
* {@code Log4jContextSelector} is set to {@code org.apache.logging.log4j.core.async.AsyncLoggerContextSelector}.
102-
* Disable by setting system property "log4j2.enable.direct.encoders" to "false".
100+
* This constant is {@code true} by default, but can be disabled using the
101+
* {@code "log4j2.enableDirectEncoders"} system property.
102+
* </p>
103103
*
104104
* @since 2.6
105105
*/

log4j-perf-test/src/main/java/org/apache/logging/log4j/perf/jmh/ConcurrentAsyncLoggerToFileBenchmark.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static class BenchmarkState {
9393
@Setup
9494
public final void before() {
9595
new File("target/ConcurrentAsyncLoggerToFileBenchmark.log").delete();
96-
System.setProperty("log4j2.is.webapp", "false");
96+
System.setProperty("log4j2.enableThreadlocals", "true");
9797
asyncLoggerType.setProperties();
9898
queueFullPolicy.setProperties();
9999
logger = LogManager.getLogger(ConcurrentAsyncLoggerToFileBenchmark.class);

log4j-perf-test/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderThrowableBenchmark.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
public class FileAppenderThrowableBenchmark {
5858
static {
5959
// log4j2
60-
System.setProperty("log4j2.is.webapp", "false");
61-
System.setProperty("log4j.configurationFile", "log4j2-perf-file-throwable.xml");
60+
System.setProperty("log4j2.enableThreadlocals", "true");
61+
System.setProperty("log4j2.configurationFile", "log4j2-perf-file-throwable.xml");
6262
// log4j 1.2
6363
System.setProperty("log4j.configuration", "log4j12-perf-file-throwable.xml");
6464
// logback

log4j-perf-test/src/main/java/org/apache/logging/log4j/perf/jmh/TextEncoderHelperBenchmark.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@
4545
// ============================== HOW TO RUN THIS TEST: ====================================
4646
//
4747
// single thread:
48-
// java -Dfile.encoding=ISO-8859-1 -Dlog4j2.is.webapp=false -Dlog4j2.enable.threadlocals=true -jar
48+
// java -Dfile.encoding=ISO-8859-1 -Dlog4j2.enableThreadlocals=true -jar
4949
// log4j-perf/target/benchmarks.jar ".*StringBuilderEncoder.*" -f 1 -wi 5 -i 10
50-
// java -Dfile.encoding=UTF8 -Dlog4j2.is.webapp=false -Dlog4j2.enable.threadlocals=true -jar
50+
// java -Dfile.encoding=UTF8 -Dlog4j2.enableThreadlocals=true -jar
5151
// log4j-perf/target/benchmarks.jar ".*StringBuilderEncoder.*" -f 1 -wi 5 -i 10
5252
//
5353
// Usage help:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="https://logging.apache.org/xml/ns"
4+
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
5+
type="changed">
6+
<description format="asciidoc">
7+
Prioritize user-defined values of `log4j2.enableThreadLocals`, `log4j2.garbagefreeThreadContextMap` and `log4j2.shutdownHookEnabled` over the value of `log4j.isWebapp`.
8+
</description>
9+
</entry>

src/site/antora/modules/ROOT/pages/manual/configuration.adoc

+3-5
Original file line numberDiff line numberDiff line change
@@ -2380,11 +2380,9 @@ or as if it is not part of a web application (when false).
23802380
| [[enableThreadlocals]]log4j2.enableThreadlocals
23812381
([[log4j2.enable.threadlocals]]log4j2.enable.threadlocals)
23822382
| LOG4J_ENABLE_THREADLOCALS
2383-
| true
2384-
| This system property can be used to switch off the use of threadlocals, which will partly disable
2385-
Log4j's garbage-free behaviour: to be fully garbage-free, Log4j stores
2386-
objects in ThreadLocal fields to reuse them, otherwise new objects are created for each log event.
2387-
Note that this property is not effective when Log4j detects it is running in a web application.
2383+
| !log4j2.isWebapp
2384+
| This system property can be used to switch off the use of those thread locals, which can cause classloader leaks in a web application.
2385+
This will partly disable Log4j's garbage-free behaviour: to be fully garbage-free, Log4j stores objects in ThreadLocal fields to reuse them, instead of creating new objects for each log event.
23882386
23892387
| [[enableDirectEncoders]]log4j2.enableDirectEncoders
23902388
([[log4j2.enable.direct.encoders]]log4j2.enable.direct.encoders)

src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ Resolves `logEvent.getMessage().getParameters()`.
10851085
Regarding garbage footprint, `stringified` flag translates to
10861086
`String.valueOf(value)`, hence mind not-`String`-typed values. Further,
10871087
`logEvent.getMessage()` is expected to implement `ParameterVisitable` interface,
1088-
which is the case if `log4j2.enableThreadLocals` property set to true.
1088+
which is the case if `log4j2.enableThreadlocals` property set to true.
10891089
====
10901090
10911091
====== Examples

0 commit comments

Comments
 (0)