Skip to content

Commit b21ce87

Browse files
committed
Prevent log4j2.isWebapp from overriding other constants
Currently, if `log4j2.isWebapp` is enabled, the effective values of the following system properties: * `log4j2.enableThreadlocals`, * `log4j2.garbagefreeThreadLocalMap`, * `log4j2.shutdownHookEnabled`. is set to `false`. After this PR: * the above mentioned constants are set to the value **explicitly** set by the user, * if the user didn't provide any value `!log4j2.isWebapp` is used.
1 parent 9a04f35 commit b21ce87

File tree

18 files changed

+77
-52
lines changed

18 files changed

+77
-52
lines changed

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

Lines changed: 3 additions & 5 deletions
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, !Constants.IS_WEB_APP)) {
330+
return GC_FREE_THREAD_CONTEXT_PROPERTY;
333331
}
334-
return WEB_APP_CONTEXT_MAP;
332+
return Constants.IS_WEB_APP ? WEB_APP_CONTEXT_MAP : COPY_ON_WRITE_CONTEXT_MAP;
335333
}
336334

337335
/**

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

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,56 @@
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 (see {@link #ENABLE_THREADLOCALS},</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+
* Kill switch to disable the usage of {@link ThreadLocal}s for object pooling
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 the usage of {@code ThreadLocal}s
62+
* for other purposes than object pooling. For example the {@link org.apache.logging.log4j.ThreadContext}
63+
* API, will user {@code ThreadLocal}s even if this constant is set to {@code false}.
4064
* </p>
65+
* @see Provider#getThreadContextMap()
4166
*/
4267
public static final boolean ENABLE_THREADLOCALS =
43-
!IS_WEB_APP && PropertiesUtil.getProperties().getBooleanProperty("log4j2.enable.threadlocals", true);
68+
PropertiesUtil.getProperties().getBooleanProperty("log4j2.enable.threadlocals", !IS_WEB_APP);
4469

4570
/**
4671
* Java major version.

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

Lines changed: 3 additions & 6 deletions
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

Lines changed: 2 additions & 3 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 4 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 2 deletions
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

0 commit comments

Comments
 (0)