This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/2.x by this push:
     new f345dedb2a Remove JANSI dependency in `2.x` (#3070)
f345dedb2a is described below

commit f345dedb2aaba25e84e03234a12666b1332a3078
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Wed Oct 16 11:12:53 2024 +0200

    Remove JANSI dependency in `2.x` (#3070)
    
    This commit:
    
    - Removes support for the outdated [Jansi 
1.x](http://fusesource.github.io/jansi/) version in `Console` appender.
    - Rewrites `JAnsiTextRenderer`, use in the `%m{ansi}` and `%ex{ansi}` 
pattern converters to use our internal ANSI support instead of Jansi.
    
    Fixes #1736.
---
 .../config/AbstractLog4j1ConfigurationTest.java    | 124 +++---
 log4j-core-test/pom.xml                            |   7 -
 .../log4j/core/test/categories/Layouts.java        |   2 -
 .../log4j/core/test/categories/package-info.java   |   4 +-
 .../appender/ConsoleAppenderAnsiMessagesMain.java  |   5 +-
 .../ConsoleAppenderAnsiStyleJira180Main.java       |   8 +-
 .../ConsoleAppenderAnsiStyleJira272Main.java       |   8 +-
 .../ConsoleAppenderAnsiStyleJira319Main.java       |   8 +-
 .../ConsoleAppenderAnsiStyleLayoutMain.java        |   6 +-
 .../ConsoleAppenderAnsiStyleNameLayoutMain.java    |   3 +-
 ...java => ConsoleAppenderAnsiXExceptionMain.java} |  15 +-
 .../ConsoleAppenderDefaultSuppressedThrowable.java |  11 +-
 .../ConsoleAppenderHighlightLayoutDefaultMain.java |   3 +-
 .../ConsoleAppenderHighlightLayoutMain.java        |   3 +-
 .../appender/ConsoleAppenderJAnsiMessageMain.java  |  84 ----
 ...leAppenderJira1002ShortThrowableLayoutMain.java |   4 +-
 .../ConsoleAppenderNoAnsiStyleLayoutMain.java      |   9 +-
 .../core/appender/JansiConsoleAppenderJira965.java |  28 --
 .../core/impl/ThrowableFormatOptionsTest.java      | 134 +++----
 .../log4j/core/pattern/JAnsiTextRendererTest.java  |  58 +++
 ...rterTest.java => MessageAnsiConverterTest.java} |   4 +-
 .../core/pattern/MessageStyledConverterTest.java   |   2 +-
 .../src/test/resources/log4j2-console-msg-ansi.xml |  30 --
 log4j-core/pom.xml                                 |   8 -
 .../log4j/core/appender/ConsoleAppender.java       | 151 +++-----
 .../log4j/core/impl/ThrowableFormatOptions.java    |  18 +-
 .../logging/log4j/core/impl/package-info.java      |   2 +-
 .../logging/log4j/core/layout/PatternLayout.java   |  13 +-
 .../logging/log4j/core/pattern/AnsiEscape.java     |   7 +-
 .../log4j/core/pattern/JAnsiTextRenderer.java      | 423 ++++++++++-----------
 .../core/pattern/MessagePatternConverter.java      |   9 +-
 .../logging/log4j/core/pattern/package-info.java   |   2 +-
 .../org/apache/logging/log4j/core/util/Loader.java |   4 +
 .../logging/log4j/smtp/SmtpAppenderAsyncTest.java  |   4 +-
 log4j-parent/pom.xml                               |   7 -
 pom.xml                                            |   7 -
 src/changelog/.2.x.x/.release-notes.adoc.ftl       |   6 +
 src/changelog/.2.x.x/1736_split_jansi_support.xml  |   8 +
 .../.2.x.x/2916_rewrite_jansi_renderer.xml         |   8 +
 src/site/antora/antora.tmpl.yml                    |   1 -
 src/site/antora/antora.yml                         |   1 -
 .../modules/ROOT/pages/manual/appenders.adoc       |  43 +--
 .../modules/ROOT/pages/manual/pattern-layout.adoc  |  23 +-
 .../ROOT/pages/manual/systemproperties.adoc        |   7 -
 .../manual/systemproperties/properties-jansi.adoc  |  32 --
 45 files changed, 513 insertions(+), 831 deletions(-)

diff --git 
a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
 
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
index 90214096ff..85851f52e6 100644
--- 
a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
+++ 
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
@@ -31,7 +31,6 @@ import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.net.URISyntaxException;
-import java.nio.file.FileSystemException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
@@ -66,7 +65,6 @@ import org.apache.logging.log4j.core.filter.Filterable;
 import org.apache.logging.log4j.core.filter.ThresholdFilter;
 import org.apache.logging.log4j.core.layout.HtmlLayout;
 import org.apache.logging.log4j.core.layout.PatternLayout;
-import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
 import org.junit.Rule;
 import org.junit.rules.TemporaryFolder;
 
@@ -78,7 +76,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
 
     abstract Configuration getConfiguration(String configResourcePrefix) 
throws URISyntaxException, IOException;
 
-    protected InputStream getResourceAsStream(final String configResource) 
throws IOException {
+    protected InputStream getResourceAsStream(final String configResource) {
         final InputStream is = 
getClass().getClassLoader().getResourceAsStream(configResource);
         assertNotNull(is);
         return is;
@@ -123,7 +121,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final ConsoleAppender appender = configuration.getAppender(name);
         assertNotNull(
                 "Missing appender '" + name + "' in configuration " + 
configResource + " → " + configuration, appender);
-        assertEquals("follow", true, getFollowProperty(appender));
+        assertTrue("follow", getFollowProperty(appender));
         assertEquals(Target.SYSTEM_ERR, appender.getTarget());
         //
         final LoggerConfig loggerConfig = 
configuration.getLoggerConfig("com.example.foo");
@@ -141,16 +139,15 @@ public abstract class AbstractLog4j1ConfigurationTest {
     }
 
     public void testRollingFileAppender() throws Exception {
-        testRollingFileAppender("config-1.2/log4j-RollingFileAppender", "RFA", 
"target/hadoop.log.%i");
+        testRollingFileAppender("config-1.2/log4j-RollingFileAppender");
     }
 
     public void testDailyRollingFileAppender() throws Exception {
-        testDailyRollingFileAppender(
-                "config-1.2/log4j-DailyRollingFileAppender", "DRFA", 
"target/hadoop.log%d{.dd-MM-yyyy}");
+        
testDailyRollingFileAppender("config-1.2/log4j-DailyRollingFileAppender");
     }
 
     public void testRollingFileAppenderWithProperties() throws Exception {
-        
testRollingFileAppender("config-1.2/log4j-RollingFileAppender-with-props", 
"RFA", "target/hadoop.log.%i");
+        
testRollingFileAppender("config-1.2/log4j-RollingFileAppender-with-props");
     }
 
     public void testSystemProperties1() throws Exception {
@@ -160,13 +157,13 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final Configuration configuration = 
getConfiguration("config-1.2/log4j-system-properties-1");
         try {
             final RollingFileAppender appender = 
configuration.getAppender("RFA");
-            assertEquals("append", false, getAppendProperty(appender));
+            assertFalse("append", getAppendProperty(appender));
             assertEquals("bufferSize", 1000, 
appender.getManager().getBufferSize());
-            assertEquals("immediateFlush", false, 
appender.getImmediateFlush());
+            assertFalse("immediateFlush", appender.getImmediateFlush());
             final DefaultRolloverStrategy rolloverStrategy =
                     (DefaultRolloverStrategy) 
appender.getManager().getRolloverStrategy();
             assertEquals(16, rolloverStrategy.getMaxIndex());
-            final CompositeTriggeringPolicy ctp = (CompositeTriggeringPolicy) 
appender.getTriggeringPolicy();
+            final CompositeTriggeringPolicy ctp = 
appender.getTriggeringPolicy();
             final TriggeringPolicy[] triggeringPolicies = 
ctp.getTriggeringPolicies();
             assertEquals(1, triggeringPolicies.length);
             final TriggeringPolicy tp = triggeringPolicies[0];
@@ -174,17 +171,11 @@ public abstract class AbstractLog4j1ConfigurationTest {
             final SizeBasedTriggeringPolicy sbtp = (SizeBasedTriggeringPolicy) 
tp;
             assertEquals(20 * 1024 * 1024, sbtp.getMaxFileSize());
             appender.stop(10, TimeUnit.SECONDS);
-            // System.out.println("expected: " + tempFileName + " Actual: " +
-            // appender.getFileName());
             assertEquals(tempFileName, appender.getFileName());
         } finally {
             configuration.start();
             configuration.stop();
-            try {
-                Files.deleteIfExists(tempFilePath);
-            } catch (final FileSystemException e) {
-                e.printStackTrace();
-            }
+            Files.deleteIfExists(tempFilePath);
         }
     }
 
@@ -195,22 +186,17 @@ public abstract class AbstractLog4j1ConfigurationTest {
         assertEquals(tmpDir + "/hadoop.log", appender.getFileName());
         appender.stop(10, TimeUnit.SECONDS);
         // Try to clean up
-        try {
-            Path path = new File(appender.getFileName()).toPath();
-            Files.deleteIfExists(path);
-            path = new File("${java.io.tmpdir}").toPath();
-            Files.deleteIfExists(path);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        Path path = new File(appender.getFileName()).toPath();
+        Files.deleteIfExists(path);
+        path = new File("${java.io.tmpdir}").toPath();
+        Files.deleteIfExists(path);
     }
 
-    private void testRollingFileAppender(final String configResource, final 
String name, final String filePattern)
-            throws Exception {
+    private void testRollingFileAppender(final String configResource) throws 
Exception {
         final Configuration configuration = getConfiguration(configResource);
-        final Appender appender = configuration.getAppender(name);
+        final Appender appender = configuration.getAppender("RFA");
         assertNotNull(appender);
-        assertEquals(name, appender.getName());
+        assertEquals("RFA", appender.getName());
         assertTrue(appender.getClass().getName(), appender instanceof 
RollingFileAppender);
         final RollingFileAppender rfa = (RollingFileAppender) appender;
 
@@ -218,11 +204,11 @@ public abstract class AbstractLog4j1ConfigurationTest {
                 "defaultRolloverStrategy", 
rfa.getManager().getRolloverStrategy() instanceof DefaultRolloverStrategy);
         assertFalse(
                 "rolloverStrategy", ((DefaultRolloverStrategy) 
rfa.getManager().getRolloverStrategy()).isUseMax());
-        assertEquals("append", false, getAppendProperty(rfa));
+        assertFalse("append", getAppendProperty(rfa));
         assertEquals("bufferSize", 1000, rfa.getManager().getBufferSize());
-        assertEquals("immediateFlush", false, rfa.getImmediateFlush());
+        assertFalse("immediateFlush", rfa.getImmediateFlush());
         assertEquals("target/hadoop.log", rfa.getFileName());
-        assertEquals(filePattern, rfa.getFilePattern());
+        assertEquals("target/hadoop.log.%i", rfa.getFilePattern());
         final TriggeringPolicy triggeringPolicy = rfa.getTriggeringPolicy();
         assertNotNull(triggeringPolicy);
         assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy 
instanceof CompositeTriggeringPolicy);
@@ -241,20 +227,19 @@ public abstract class AbstractLog4j1ConfigurationTest {
         configuration.stop();
     }
 
-    private void testDailyRollingFileAppender(final String configResource, 
final String name, final String filePattern)
-            throws Exception {
+    private void testDailyRollingFileAppender(final String configResource) 
throws Exception {
         final Configuration configuration = getConfiguration(configResource);
         try {
-            final Appender appender = configuration.getAppender(name);
+            final Appender appender = configuration.getAppender("DRFA");
             assertNotNull(appender);
-            assertEquals(name, appender.getName());
+            assertEquals("DRFA", appender.getName());
             assertTrue(appender.getClass().getName(), appender instanceof 
RollingFileAppender);
             final RollingFileAppender rfa = (RollingFileAppender) appender;
-            assertEquals("append", false, getAppendProperty(rfa));
+            assertFalse("append", getAppendProperty(rfa));
             assertEquals("bufferSize", 1000, rfa.getManager().getBufferSize());
-            assertEquals("immediateFlush", false, rfa.getImmediateFlush());
+            assertFalse("immediateFlush", rfa.getImmediateFlush());
             assertEquals("target/hadoop.log", rfa.getFileName());
-            assertEquals(filePattern, rfa.getFilePattern());
+            assertEquals("target/hadoop.log%d{.dd-MM-yyyy}", 
rfa.getFilePattern());
             final TriggeringPolicy triggeringPolicy = 
rfa.getTriggeringPolicy();
             assertNotNull(triggeringPolicy);
             assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy 
instanceof CompositeTriggeringPolicy);
@@ -275,8 +260,8 @@ public abstract class AbstractLog4j1ConfigurationTest {
         }
     }
 
-    private Layout<?> testFile(final String configResource) throws Exception {
-        final Configuration configuration = getConfiguration(configResource);
+    private Layout<?> testFile() throws Exception {
+        final Configuration configuration = 
getConfiguration("config-1.2/log4j-file-SimpleLayout");
         final FileAppender appender = configuration.getAppender("File");
         assertNotNull(appender);
         assertEquals("target/mylog.txt", appender.getFileName());
@@ -284,9 +269,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final LoggerConfig loggerConfig = 
configuration.getLoggerConfig("com.example.foo");
         assertNotNull(loggerConfig);
         assertEquals(Level.DEBUG, loggerConfig.getLevel());
-        assertEquals("append", false, getAppendProperty(appender));
+        assertFalse("append", getAppendProperty(appender));
         assertEquals("bufferSize", 1000, 
appender.getManager().getBufferSize());
-        assertEquals("immediateFlush", false, appender.getImmediateFlush());
+        assertFalse("immediateFlush", appender.getImmediateFlush());
         configuration.start();
         configuration.stop();
         return appender.getLayout();
@@ -316,7 +301,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
     }
 
     public void testFileSimpleLayout() throws Exception {
-        final PatternLayout layout = (PatternLayout) 
testFile("config-1.2/log4j-file-SimpleLayout");
+        final PatternLayout layout = (PatternLayout) testFile();
         assertEquals("%v1Level - %m%n", layout.getConversionPattern());
     }
 
@@ -328,14 +313,11 @@ public abstract class AbstractLog4j1ConfigurationTest {
         assertTrue(appender.getClass().getName(), appender instanceof 
NullAppender);
     }
 
-    private boolean getFollowProperty(final ConsoleAppender consoleAppender)
-            throws Exception, NoSuchFieldException, IllegalAccessException {
-        final CloseShieldOutputStream wrapperStream =
-                (CloseShieldOutputStream) 
getOutputStream(consoleAppender.getManager());
-        final Field delegateField = 
CloseShieldOutputStream.class.getDeclaredField("delegate");
-        delegateField.setAccessible(true);
-        final boolean follow = 
!System.out.equals(delegateField.get(wrapperStream));
-        return follow;
+    private boolean getFollowProperty(final ConsoleAppender consoleAppender) 
throws Exception {
+        OutputStream outputStream = 
getOutputStream(consoleAppender.getManager());
+        String className = outputStream.getClass().getName();
+        return className.endsWith("ConsoleAppender$SystemErrStream")
+                || className.endsWith("ConsoleAppender$SystemOutStream");
     }
 
     private boolean getAppendProperty(final RollingFileAppender appender) 
throws Exception {
@@ -383,7 +365,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final HtmlLayout htmlLayout = (HtmlLayout) testLayout(config, 
"HTMLLayout");
         assertNotNull(htmlLayout);
         assertEquals("title", "Log4J Log Messages", htmlLayout.getTitle());
-        assertEquals("locationInfo", false, htmlLayout.isLocationInfo());
+        assertFalse("locationInfo", htmlLayout.isLocationInfo());
         // PatternLayout
         final PatternLayout patternLayout = (PatternLayout) testLayout(config, 
"PatternLayout");
         assertNotNull(patternLayout);
@@ -403,7 +385,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
         assertNotNull(consoleAppender);
         assertEquals("target", Target.SYSTEM_OUT, consoleAppender.getTarget());
         final boolean follow = getFollowProperty(consoleAppender);
-        assertEquals("follow", false, follow);
+        assertFalse("follow", follow);
         // DailyRollingFileAppender
         final RollingFileAppender dailyRollingFileAppender = 
config.getAppender("DailyRollingFileAppender");
         assertNotNull(dailyRollingFileAppender);
@@ -411,15 +393,15 @@ public abstract class AbstractLog4j1ConfigurationTest {
                 "equivalent file pattern",
                 "target/dailyRollingFileAppender%d{.yyyy-MM-dd}",
                 dailyRollingFileAppender.getFilePattern());
-        assertEquals("append", true, 
getAppendProperty(dailyRollingFileAppender));
+        assertTrue("append", getAppendProperty(dailyRollingFileAppender));
         assertEquals("bufferSize", 8192, 
dailyRollingFileAppender.getManager().getBufferSize());
-        assertEquals("immediateFlush", true, 
dailyRollingFileAppender.getImmediateFlush());
+        assertTrue("immediateFlush", 
dailyRollingFileAppender.getImmediateFlush());
         // FileAppender
         final FileAppender fileAppender = config.getAppender("FileAppender");
         assertNotNull(fileAppender);
-        assertEquals("append", true, getAppendProperty(fileAppender));
+        assertTrue("append", getAppendProperty(fileAppender));
         assertEquals("bufferSize", 8192, 
fileAppender.getManager().getBufferSize());
-        assertEquals("immediateFlush", true, fileAppender.getImmediateFlush());
+        assertTrue("immediateFlush", fileAppender.getImmediateFlush());
         // RollingFileAppender
         final RollingFileAppender rollingFileAppender = 
config.getAppender("RollingFileAppender");
         assertNotNull(rollingFileAppender);
@@ -433,9 +415,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final DefaultRolloverStrategy strategy =
                 (DefaultRolloverStrategy) 
rollingFileAppender.getManager().getRolloverStrategy();
         assertEquals("maxBackupIndex", 1, strategy.getMaxIndex());
-        assertEquals("append", true, getAppendProperty(rollingFileAppender));
+        assertTrue("append", getAppendProperty(rollingFileAppender));
         assertEquals("bufferSize", 8192, 
rollingFileAppender.getManager().getBufferSize());
-        assertEquals("immediateFlush", true, 
rollingFileAppender.getImmediateFlush());
+        assertTrue("immediateFlush", rollingFileAppender.getImmediateFlush());
         config.start();
         config.stop();
     }
@@ -443,7 +425,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
     /**
      * Checks a hierarchy of filters.
      *
-     * @param filter
+     * @param filter A filter
      * @return the number of filters
      */
     private int checkFilters(final org.apache.logging.log4j.core.Filter 
filter) {
@@ -467,7 +449,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
     /**
      * Checks a hierarchy of filters.
      *
-     * @param filter
+     * @param filter A filter
      * @return the number of filters
      */
     private int checkFilters(final org.apache.log4j.spi.Filter filter) {
@@ -581,9 +563,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         appender = configuration.getAppender("DEFAULT_TIME");
         assertTrue("is RollingFileAppender", appender instanceof 
RollingFileAppender);
         final RollingFileAppender defaultTime = (RollingFileAppender) appender;
-        assertEquals("append", true, defaultTime.getManager().isAppend());
+        assertTrue("append", defaultTime.getManager().isAppend());
         assertEquals("bufferSize", 8192, 
defaultTime.getManager().getBufferSize());
-        assertEquals("immediateFlush", true, defaultTime.getImmediateFlush());
+        assertTrue("immediateFlush", defaultTime.getImmediateFlush());
         assertEquals("fileName", 
"target/EnhancedRollingFileAppender/defaultTime.log", 
defaultTime.getFileName());
         assertEquals(
                 "filePattern",
@@ -595,9 +577,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         appender = configuration.getAppender("DEFAULT_SIZE");
         assertTrue("is RollingFileAppender", appender instanceof 
RollingFileAppender);
         final RollingFileAppender defaultSize = (RollingFileAppender) appender;
-        assertEquals("append", true, defaultSize.getManager().isAppend());
+        assertTrue("append", defaultSize.getManager().isAppend());
         assertEquals("bufferSize", 8192, 
defaultSize.getManager().getBufferSize());
-        assertEquals("immediateFlush", true, defaultSize.getImmediateFlush());
+        assertTrue("immediateFlush", defaultSize.getImmediateFlush());
         assertEquals("fileName", 
"target/EnhancedRollingFileAppender/defaultSize.log", 
defaultSize.getFileName());
         assertEquals(
                 "filePattern", 
"target/EnhancedRollingFileAppender/defaultSize.%i.log", 
defaultSize.getFilePattern());
@@ -613,9 +595,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         appender = configuration.getAppender("TIME");
         assertTrue("is RollingFileAppender", appender instanceof 
RollingFileAppender);
         final RollingFileAppender time = (RollingFileAppender) appender;
-        assertEquals("append", false, time.getManager().isAppend());
+        assertFalse("append", time.getManager().isAppend());
         assertEquals("bufferSize", 1000, time.getManager().getBufferSize());
-        assertEquals("immediateFlush", false, time.getImmediateFlush());
+        assertFalse("immediateFlush", time.getImmediateFlush());
         assertEquals("fileName", 
"target/EnhancedRollingFileAppender/time.log", time.getFileName());
         assertEquals(
                 "filePattern", 
"target/EnhancedRollingFileAppender/time.%d{yyyy-MM-dd}.log", 
time.getFilePattern());
@@ -625,9 +607,9 @@ public abstract class AbstractLog4j1ConfigurationTest {
         appender = configuration.getAppender("SIZE");
         assertTrue("is RollingFileAppender", appender instanceof 
RollingFileAppender);
         final RollingFileAppender size = (RollingFileAppender) appender;
-        assertEquals("append", false, size.getManager().isAppend());
+        assertFalse("append", size.getManager().isAppend());
         assertEquals("bufferSize", 1000, size.getManager().getBufferSize());
-        assertEquals("immediateFlush", false, size.getImmediateFlush());
+        assertFalse("immediateFlush", size.getImmediateFlush());
         assertEquals("fileName", 
"target/EnhancedRollingFileAppender/size.log", size.getFileName());
         assertEquals("filePattern", 
"target/EnhancedRollingFileAppender/size.%i.log", size.getFilePattern());
         policy = size.getTriggeringPolicy();
diff --git a/log4j-core-test/pom.xml b/log4j-core-test/pom.xml
index 56f7fd885f..8c8cbc19bb 100644
--- a/log4j-core-test/pom.xml
+++ b/log4j-core-test/pom.xml
@@ -242,13 +242,6 @@
       <scope>test</scope>
     </dependency>
 
-    <!-- Required for console color support in Windows -->
-    <dependency>
-      <groupId>org.fusesource.jansi</groupId>
-      <artifactId>jansi</artifactId>
-      <scope>test</scope>
-    </dependency>
-
     <!-- Used for JMS appenders (needs an implementation of course) -->
     <dependency>
       <groupId>javax.jms</groupId>
diff --git 
a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
index 0cdc8b4540..89057c90c0 100644
--- 
a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
+++ 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
@@ -22,8 +22,6 @@ package org.apache.logging.log4j.core.test.categories;
 public interface Layouts {
     interface Csv {}
 
-    interface Jansi {}
-
     interface Json {}
 
     interface Xml {}
diff --git 
a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
index a299ed2b4c..fbbe417285 100644
--- 
a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
+++ 
b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
@@ -20,8 +20,10 @@
  * integration tests, an appropriate category interface should be specified.
  */
 @Export
-@Version("2.20.1")
+@Version("2.20.2")
+@BaselineIgnore("2.25.0")
 package org.apache.logging.log4j.core.test.categories;
 
+import aQute.bnd.annotation.baseline.BaselineIgnore;
 import org.osgi.annotation.bundle.Export;
 import org.osgi.annotation.versioning.Version;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
index 3088ca2bc1..a44d064ab4 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
@@ -30,7 +30,7 @@ import org.apache.logging.log4j.core.config.Configurator;
  * </p>
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain 
log4j-core/target/test-classes/log4j2-console.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain 
log4j-core/target/test-classes/log4j2-console.xml
  * </pre>
  */
 public class ConsoleAppenderAnsiMessagesMain {
@@ -38,8 +38,7 @@ public class ConsoleAppenderAnsiMessagesMain {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderAnsiMessagesMain.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        try (final LoggerContext ctx = Configurator.initialize(
+        try (final LoggerContext ignored = Configurator.initialize(
                 ConsoleAppenderAnsiMessagesMain.class.getName(), 
"target/test-classes/log4j2-console.xml")) {
             LOG.fatal("\u001b[1;35mFatal message.\u001b[0m");
             LOG.error("\u001b[1;31mError message.\u001b[0m");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
index dffc5b4289..bd8491c666 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
@@ -23,13 +23,13 @@ import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configurator;
 
 /**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-180
+ * Tests <a 
href="https://issues.apache.org/jira/browse/LOG4J2-180";>LOG4J2-180</a>
  * <p>
  * Running from a Windows command line from the root of the project:
  * </p>
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main 
log4j-core/target/test-classes/log4j2-180.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main 
log4j-core/target/test-classes/log4j2-180.xml
  * </pre>
  */
 public class ConsoleAppenderAnsiStyleJira180Main {
@@ -37,10 +37,8 @@ public class ConsoleAppenderAnsiStyleJira180Main {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderAnsiStyleJira180Main.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
         final String config = args.length == 0 ? 
"target/test-classes/log4j2-180.xml" : args[0];
-        try (final LoggerContext ctx =
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config)) {
             LOG.fatal("Fatal message.");
             LOG.error("Error message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
index 0f2844abe7..65a4ed1ee7 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
@@ -23,12 +23,12 @@ import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configurator;
 
 /**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-272
+ * Tests <a 
href="https://issues.apache.org/jira/browse/LOG4J2-272";>LOG4J2-272</a>
  * <p>
  * Running from a Windows command line from the root of the project:
  * </p>
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main 
log4j-core/target/test-classes/log4j2-272.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main 
log4j-core/target/test-classes/log4j2-272.xml
  * </pre>
  */
 public class ConsoleAppenderAnsiStyleJira272Main {
@@ -36,10 +36,8 @@ public class ConsoleAppenderAnsiStyleJira272Main {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderAnsiStyleJira272Main.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
         final String config = args.length == 0 ? 
"target/test-classes/log4j2-272.xml" : args[0];
-        try (final LoggerContext ctx =
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config)) {
             LOG.fatal("Fatal message.");
             LOG.error("Error message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
index 48681a85f7..957a58e9bf 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
@@ -23,13 +23,13 @@ import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configurator;
 
 /**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-319
+ * Tests <a 
href="https://issues.apache.org/jira/browse/LOG4J2-319";>LOG4J2-319</a>
  * <p>
  * Running from a Windows command line from the root of the project:
  * </p>
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main 
log4j-core/target/test-classes/log4j2-319.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main 
log4j-core/target/test-classes/log4j2-319.xml
  * </pre>
  */
 public class ConsoleAppenderAnsiStyleJira319Main {
@@ -37,10 +37,8 @@ public class ConsoleAppenderAnsiStyleJira319Main {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderAnsiStyleJira319Main.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
         final String config = args.length == 0 ? 
"target/test-classes/log4j2-319.xml" : args[0];
-        try (final LoggerContext ctx =
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config)) {
             LOG.fatal("Fatal message.");
             LOG.error("Error message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
index 87730d9a5a..2ef1c52c9f 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
@@ -35,7 +35,7 @@ import org.junit.Test;
  * </pre>
  * or:
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
  * </pre>
  *
  */
@@ -54,11 +54,9 @@ public class ConsoleAppenderAnsiStyleLayoutMain {
     }
 
     public void test(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
         final String config =
                 args == null || args.length == 0 ? 
"target/test-classes/log4j2-console-style-ansi.xml" : args[0];
-        try (final LoggerContext ctx =
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config)) {
             final Logger logger = 
LogManager.getLogger(ConsoleAppenderAnsiStyleLayoutMain.class);
             logger.fatal("Fatal message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
index 9088b75d47..5cdc81ee45 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderAnsiStyleNameLayoutMain {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderAnsiStyleNameLayoutMain.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        try (final LoggerContext ctx = Configurator.initialize(
+        try (final LoggerContext ignored = Configurator.initialize(
                 ConsoleAppenderAnsiMessagesMain.class.getName(),
                 "target/test-classes/log4j2-console-style-name-ansi.xml")) {
             LOG.fatal("Fatal message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
similarity index 78%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java
rename to 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
index d681e02c75..ee062add98 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
@@ -22,9 +22,7 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configurator;
-import org.apache.logging.log4j.core.test.categories.Layouts;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 
 /**
  * Shows how to use ANSI escape codes to color messages. Each message is 
printed to the console in color, but the rest
@@ -34,21 +32,20 @@ import org.junit.experimental.categories.Category;
  * </p>
  *
  * <pre>
- * mvn 
-Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain
 test
+ * mvn 
-Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiXExceptionMain 
test
  * </pre>
  *
  * or, on Windows:
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain 
log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiXExceptionMain 
log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
  * </pre>
  *
  */
-@Category(Layouts.Jansi.class)
-public class ConsoleAppenderJAnsiXExceptionMain {
+public class ConsoleAppenderAnsiXExceptionMain {
 
     public static void main(final String[] args) {
-        new ConsoleAppenderJAnsiXExceptionMain().test(args);
+        new ConsoleAppenderAnsiXExceptionMain().test(args);
     }
 
     /**
@@ -60,12 +57,10 @@ public class ConsoleAppenderJAnsiXExceptionMain {
     }
 
     public void test(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
         final String config =
                 args == null || args.length == 0 ? 
"target/test-classes/log4j2-console-xex-ansi.xml" : args[0];
         final LoggerContext ctx = 
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config);
-        final Logger logger = 
LogManager.getLogger(ConsoleAppenderJAnsiXExceptionMain.class);
+        final Logger logger = 
LogManager.getLogger(ConsoleAppenderAnsiXExceptionMain.class);
         try {
             Files.getFileStore(Paths.get("?BOGUS?"));
         } catch (final Exception e) {
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
index 8553eb3f1d..2432df32c9 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
@@ -31,7 +31,7 @@ import org.apache.logging.log4j.core.config.Configurator;
  * </p>
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
  * </pre>
  */
 public class ConsoleAppenderDefaultSuppressedThrowable {
@@ -41,12 +41,11 @@ public class ConsoleAppenderDefaultSuppressedThrowable {
     public static void main(final String[] args) {
         final String config =
                 args.length == 0 ? 
"target/test-classes/log4j2-console-default-suppressed-throwable.xml" : args[0];
-        test(args, config);
+        test(config);
     }
 
-    static void test(final String[] args, final String config) {
-        // System.out.println(System.getProperty("java.class.path"));
-        try (final LoggerContext ctx =
+    static void test(final String config) {
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderDefaultSuppressedThrowable.class.getName(),
 config)) {
             final IOException ioEx = new IOException("test suppressed");
             ioEx.addSuppressed(new IOException("test suppressed 1", new 
IOException("test 1")));
@@ -55,8 +54,6 @@ public class ConsoleAppenderDefaultSuppressedThrowable {
             ioEx.addSuppressed(new IOException("test suppressed 2", ioEx2));
             final IOException e = new IOException("test", ioEx);
             LOG.error("Error message {}, suppressed?", "Hi", e);
-            System.out.println("printStackTrace");
-            e.printStackTrace();
         }
     }
 }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
index 7a1b7cf616..d9b5eeba27 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderHighlightLayoutDefaultMain {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderHighlightLayoutDefaultMain.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        try (final LoggerContext ctx = Configurator.initialize(
+        try (final LoggerContext ignored = Configurator.initialize(
                 ConsoleAppenderAnsiMessagesMain.class.getName(),
                 "target/test-classes/log4j2-console-highlight-default.xml")) {
             LOG.fatal("Fatal message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
index dbb6958ea2..ad86c24570 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderHighlightLayoutMain {
     private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderHighlightLayoutMain.class);
 
     public static void main(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        try (final LoggerContext ctx = Configurator.initialize(
+        try (final LoggerContext ignored = Configurator.initialize(
                 ConsoleAppenderAnsiMessagesMain.class.getName(), 
"target/test-classes/log4j2-console-highlight.xml")) {
             LOG.fatal("Fatal message.");
             LOG.error("Error message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
deleted file mode 100644
index 56cce35a74..0000000000
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.logging.log4j.core.appender;
-
-import static org.fusesource.jansi.Ansi.Color.CYAN;
-import static org.fusesource.jansi.Ansi.Color.RED;
-import static org.fusesource.jansi.Ansi.ansi;
-
-import java.util.Map.Entry;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.Configurator;
-import org.apache.logging.log4j.core.test.categories.Layouts;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
-
-/**
- * Shows how to use ANSI escape codes to color messages. Each message is 
printed to the console in color, but the rest
- * of the log entry (time stamp for example) is in the default color for that 
console.
- * <p>
- * Running from a Windows command line from the root of the project:
- * </p>
- *
- * <pre>
- * mvn 
-Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain 
test
- * </pre>
- *
- * or, on Windows:
- *
- * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain 
log4j-core/src/test/resources/log4j2-console-msg-ansi.xml
- * </pre>
- *
- */
-@Category(Layouts.Jansi.class)
-public class ConsoleAppenderJAnsiMessageMain {
-
-    public static void main(final String[] args) {
-        new ConsoleAppenderJAnsiMessageMain().test(args);
-    }
-
-    /**
-     * This is a @Test method to make it easy to run from a command line with 
{@code mvn -Dtest=FQCN test}
-     */
-    @Test
-    @ResourceLock(Resources.SYSTEM_PROPERTIES)
-    public void test() {
-        test(null);
-    }
-
-    public void test(final String[] args) {
-        System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: 
explicitly enable
-        // System.out.println(System.getProperty("java.class.path"));
-        final String config =
-                args == null || args.length == 0 ? 
"target/test-classes/log4j2-console-msg-ansi.xml" : args[0];
-        try (final LoggerContext ctx =
-                
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), 
config)) {
-            final Logger logger = 
LogManager.getLogger(ConsoleAppenderJAnsiMessageMain.class);
-            logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" 
World").reset());
-            // JAnsi format:
-            // logger.info("@|red Hello|@ @|cyan World|@");
-            for (final Entry<Object, Object> entry : 
System.getProperties().entrySet()) {
-                logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", 
entry.getKey(), entry.getValue());
-            }
-        }
-    }
-}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
index b75e3e0325..b1177acdd2 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
@@ -21,7 +21,7 @@ package org.apache.logging.log4j.core.appender;
  */
 public class ConsoleAppenderJira1002ShortThrowableLayoutMain {
 
-    public static void main(final String[] args) {
-        ConsoleAppenderNoAnsiStyleLayoutMain.test(args, 
"target/test-classes/log4j2-1002.xml");
+    public static void main() {
+        
ConsoleAppenderNoAnsiStyleLayoutMain.test("target/test-classes/log4j2-1002.xml");
     }
 }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
index 1c35103862..1165fc6a60 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
@@ -30,7 +30,7 @@ import org.apache.logging.log4j.core.config.Configurator;
  * </p>
  *
  * <pre>
- * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes
 org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
  * </pre>
  */
 public class ConsoleAppenderNoAnsiStyleLayoutMain {
@@ -43,12 +43,11 @@ public class ConsoleAppenderNoAnsiStyleLayoutMain {
 
     public static void main(final String[] args) {
         final String config = args.length == 0 ? 
"target/test-classes/log4j2-console-style-no-ansi.xml" : args[0];
-        test(args, config);
+        test(config);
     }
 
-    static void test(final String[] args, final String config) {
-        // System.out.println(System.getProperty("java.class.path"));
-        try (final LoggerContext ctx =
+    static void test(final String config) {
+        try (final LoggerContext ignored =
                 
Configurator.initialize(ConsoleAppenderNoAnsiStyleLayoutMain.class.getName(), 
config)) {
             LOG.fatal("Fatal message.");
             LOG.error("Error message.");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
deleted file mode 100644
index 8bdd3e13ef..0000000000
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.logging.log4j.core.appender;
-
-import org.slf4j.LoggerFactory;
-
-public class JansiConsoleAppenderJira965 {
-
-    public static void main(final String[] args) {
-        System.out.println("Able to print on Windows");
-        LoggerFactory.getLogger(JansiConsoleAppenderJira965.class);
-        System.out.println("Unable to print on Windows");
-    }
-}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
index 4719db8563..10dea80250 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
@@ -16,26 +16,27 @@
  */
 package org.apache.logging.log4j.core.impl;
 
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.apache.logging.log4j.util.Strings.toRootUpperCase;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import org.apache.logging.log4j.core.pattern.AnsiEscape;
 import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
 import org.apache.logging.log4j.core.pattern.TextRenderer;
 import org.apache.logging.log4j.util.Strings;
-import org.fusesource.jansi.AnsiRenderer.Code;
 import org.junit.jupiter.api.Test;
 
 /**
  * Unit tests for {@code ThrowableFormatOptions}.
  */
-public final class ThrowableFormatOptionsTest {
+final class ThrowableFormatOptionsTest {
 
     /**
      * Runs a given test comparing against the expected values.
@@ -71,7 +72,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable} with null options.
      */
     @Test
-    public void testNull() {
+    void testNull() {
         test(null, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
     }
 
@@ -79,7 +80,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable}
      */
     @Test
-    public void testEmpty() {
+    void testEmpty() {
         test(new String[] {}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
     }
 
@@ -87,7 +88,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{} } with null option value.
      */
     @Test
-    public void testOneNullElement() {
+    void testOneNullElement() {
         test(new String[] {null}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, 
null);
     }
 
@@ -95,7 +96,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{} }
      */
     @Test
-    public void testOneEmptyElement() {
+    void testOneEmptyElement() {
         test(new String[] {""}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, 
null);
     }
 
@@ -103,7 +104,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full} }
      */
     @Test
-    public void testFull() {
+    void testFull() {
         test(new String[] {"full"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, 
null);
     }
 
@@ -111,7 +112,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{ansi} }
      */
     @Test
-    public void testFullAnsi() {
+    void testFullAnsi() {
         final ThrowableFormatOptions tfo =
                 test(new String[] {"full", "ansi"}, Integer.MAX_VALUE, 
Strings.LINE_SEPARATOR, null);
         testFullAnsiEmptyConfig(tfo);
@@ -121,7 +122,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{ansi()} }
      */
     @Test
-    public void testFullAnsiEmptyConfig() {
+    void testFullAnsiEmptyConfig() {
         final ThrowableFormatOptions tfo =
                 test(new String[] {"full", "ansi()"}, Integer.MAX_VALUE, 
Strings.LINE_SEPARATOR, null);
         testFullAnsiEmptyConfig(tfo);
@@ -130,34 +131,34 @@ public final class ThrowableFormatOptionsTest {
     private void testFullAnsiEmptyConfig(final ThrowableFormatOptions tfo) {
         final TextRenderer textRenderer = tfo.getTextRenderer();
         assertNotNull(textRenderer);
-        assertTrue(textRenderer instanceof JAnsiTextRenderer);
-        final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) 
textRenderer;
-        final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
+        assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+        final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) 
textRenderer;
+        final Map<String, String> styleMap = ansiRenderer.getStyleMap();
         // We have defaults
         assertFalse(styleMap.isEmpty());
-        assertNotNull(styleMap.get("Name"));
+        assertNotNull(styleMap.get(toRootUpperCase("Name")));
     }
 
     /**
      * Test {@code %throwable{full}{ansi(Warning=red))} }
      */
     @Test
-    public void testFullAnsiWithCustomStyle() {
+    void testFullAnsiWithCustomStyle() {
         final ThrowableFormatOptions tfo =
                 test(new String[] {"full", "ansi(Warning=red)"}, 
Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
         final TextRenderer textRenderer = tfo.getTextRenderer();
         assertNotNull(textRenderer);
-        assertTrue(textRenderer instanceof JAnsiTextRenderer);
-        final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) 
textRenderer;
-        final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
-        assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
+        assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+        final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) 
textRenderer;
+        final Map<String, String> styleMap = ansiRenderer.getStyleMap();
+        
assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
     }
 
     /**
      * Test {@code %throwable{full}{ansi(Warning=red Key=blue Value=cyan))} }
      */
     @Test
-    public void testFullAnsiWithCustomStyles() {
+    void testFullAnsiWithCustomStyles() {
         final ThrowableFormatOptions tfo = test(
                 new String[] {"full", "ansi(Warning=red Key=blue Value=cyan)"},
                 Integer.MAX_VALUE,
@@ -165,19 +166,19 @@ public final class ThrowableFormatOptionsTest {
                 null);
         final TextRenderer textRenderer = tfo.getTextRenderer();
         assertNotNull(textRenderer);
-        assertTrue(textRenderer instanceof JAnsiTextRenderer);
-        final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) 
textRenderer;
-        final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
-        assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
-        assertArrayEquals(new Code[] {Code.BLUE}, styleMap.get("Key"));
-        assertArrayEquals(new Code[] {Code.CYAN}, styleMap.get("Value"));
+        assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+        final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) 
textRenderer;
+        final Map<String, String> styleMap = ansiRenderer.getStyleMap();
+        
assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
+        
assertThat(styleMap.get(toRootUpperCase("Key"))).isEqualTo(AnsiEscape.createSequence("BLUE"));
+        
assertThat(styleMap.get(toRootUpperCase("Value"))).isEqualTo(AnsiEscape.createSequence("CYAN"));
     }
 
     /**
      * Test {@code %throwable{full}{ansi(Warning=red Key=blue,bg_red 
Value=cyan,bg_black,underline)} }
      */
     @Test
-    public void testFullAnsiWithCustomComplexStyles() {
+    void testFullAnsiWithCustomComplexStyles() {
         final ThrowableFormatOptions tfo = test(
                 new String[] {"full", "ansi(Warning=red Key=blue,bg_red 
Value=cyan,bg_black,underline)"},
                 Integer.MAX_VALUE,
@@ -185,19 +186,20 @@ public final class ThrowableFormatOptionsTest {
                 null);
         final TextRenderer textRenderer = tfo.getTextRenderer();
         assertNotNull(textRenderer);
-        assertTrue(textRenderer instanceof JAnsiTextRenderer);
-        final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) 
textRenderer;
-        final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
-        assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
-        assertArrayEquals(new Code[] {Code.BLUE, Code.BG_RED}, 
styleMap.get("Key"));
-        assertArrayEquals(new Code[] {Code.CYAN, Code.BG_BLACK, 
Code.UNDERLINE}, styleMap.get("Value"));
+        assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+        final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) 
textRenderer;
+        final Map<String, String> styleMap = ansiRenderer.getStyleMap();
+        
assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
+        
assertThat(styleMap.get(toRootUpperCase("Key"))).isEqualTo(AnsiEscape.createSequence("BLUE",
 "BG_RED"));
+        assertThat(styleMap.get(toRootUpperCase("Value")))
+                .isEqualTo(AnsiEscape.createSequence("CYAN", "BG_BLACK", 
"UNDERLINE"));
     }
 
     /**
      * Test {@code %throwable{none} }
      */
     @Test
-    public void testNone() {
+    void testNone() {
         test(new String[] {"none"}, 0, Strings.LINE_SEPARATOR, null);
     }
 
@@ -205,7 +207,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short} }
      */
     @Test
-    public void testShort() {
+    void testShort() {
         test(new String[] {"short"}, 2, Strings.LINE_SEPARATOR, null);
     }
 
@@ -213,7 +215,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{10} }
      */
     @Test
-    public void testDepth() {
+    void testDepth() {
         test(new String[] {"10"}, 10, Strings.LINE_SEPARATOR, null);
     }
 
@@ -221,7 +223,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{separator(|)} }
      */
     @Test
-    public void testSeparator() {
+    void testSeparator() {
         test(new String[] {"separator(|)"}, Integer.MAX_VALUE, "|", null);
     }
 
@@ -229,7 +231,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{separator()} }
      */
     @Test
-    public void testSeparatorAsEmpty() {
+    void testSeparatorAsEmpty() {
         test(new String[] {"separator()"}, Integer.MAX_VALUE, Strings.EMPTY, 
null);
     }
 
@@ -237,7 +239,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{separator(\n)} }
      */
     @Test
-    public void testSeparatorAsDefaultLineSeparator() {
+    void testSeparatorAsDefaultLineSeparator() {
         test(
                 new String[] {"separator(" + Strings.LINE_SEPARATOR + ')'},
                 Integer.MAX_VALUE,
@@ -249,7 +251,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{separator( | )} }
      */
     @Test
-    public void testSeparatorAsMultipleCharacters() {
+    void testSeparatorAsMultipleCharacters() {
         test(new String[] {"separator( | )"}, Integer.MAX_VALUE, " | ", null);
     }
 
@@ -257,7 +259,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{separator(|)} }
      */
     @Test
-    public void testFullAndSeparator() {
+    void testFullAndSeparator() {
         test(new String[] {"full", "separator(|)"}, Integer.MAX_VALUE, "|", 
null);
     }
 
@@ -265,7 +267,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{filters(org.junit)}{separator(|)} }
      */
     @Test
-    public void testFullAndFiltersAndSeparator() {
+    void testFullAndFiltersAndSeparator() {
         test(
                 new String[] {"full", "filters(org.junit)", "separator(|)"},
                 Integer.MAX_VALUE,
@@ -277,7 +279,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none}{separator(|)} }
      */
     @Test
-    public void testNoneAndSeparator() {
+    void testNoneAndSeparator() {
         test(new String[] {"none", "separator(|)"}, 0, "|", null);
     }
 
@@ -285,7 +287,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short}{separator(|)} }
      */
     @Test
-    public void testShortAndSeparator() {
+    void testShortAndSeparator() {
         test(new String[] {"short", "separator(|)"}, 2, "|", null);
     }
 
@@ -293,7 +295,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{10}{separator(|)} }
      */
     @Test
-    public void testDepthAndSeparator() {
+    void testDepthAndSeparator() {
         test(new String[] {"10", "separator(|)"}, 10, "|", null);
     }
 
@@ -301,7 +303,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{filters(packages)} }
      */
     @Test
-    public void testFilters() {
+    void testFilters() {
         test(
                 new String[] {"filters(packages)"},
                 Integer.MAX_VALUE,
@@ -313,7 +315,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{filters()} }
      */
     @Test
-    public void testFiltersAsEmpty() {
+    void testFiltersAsEmpty() {
         test(new String[] {"filters()"}, Integer.MAX_VALUE, 
Strings.LINE_SEPARATOR, null);
     }
 
@@ -321,7 +323,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{filters(package1,package2)} }
      */
     @Test
-    public void testFiltersAsMultiplePackages() {
+    void testFiltersAsMultiplePackages() {
         test(
                 new String[] {"filters(package1,package2)"},
                 Integer.MAX_VALUE,
@@ -333,7 +335,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{filters(packages)} }
      */
     @Test
-    public void testFullAndFilters() {
+    void testFullAndFilters() {
         test(
                 new String[] {"full", "filters(packages)"},
                 Integer.MAX_VALUE,
@@ -345,7 +347,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none}{filters(packages)} }
      */
     @Test
-    public void testNoneAndFilters() {
+    void testNoneAndFilters() {
         test(
                 new String[] {"none", "filters(packages)"},
                 0,
@@ -357,7 +359,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short}{filters(packages)} }
      */
     @Test
-    public void testShortAndFilters() {
+    void testShortAndFilters() {
         test(
                 new String[] {"short", "filters(packages)"},
                 2,
@@ -369,7 +371,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{10}{filters(packages)} }
      */
     @Test
-    public void testDepthAndFilters() {
+    void testDepthAndFilters() {
         test(
                 new String[] {"10", "filters(packages)"},
                 10,
@@ -381,7 +383,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{separator(|)}{filters(packages)} }
      */
     @Test
-    public void testFullAndSeparatorAndFilter() {
+    void testFullAndSeparatorAndFilter() {
         test(
                 new String[] {"full", "separator(|)", "filters(packages)"},
                 Integer.MAX_VALUE,
@@ -393,7 +395,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{separator(|)}{filters(package1,package2)} }
      */
     @Test
-    public void testFullAndSeparatorAndFilters() {
+    void testFullAndSeparatorAndFilters() {
         test(
                 new String[] {"full", "separator(|)", 
"filters(package1,package2)"},
                 Integer.MAX_VALUE,
@@ -405,7 +407,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none}{separator(|)}{filters(packages)} }
      */
     @Test
-    public void testNoneAndSeparatorAndFilters() {
+    void testNoneAndSeparatorAndFilters() {
         test(new String[] {"none", "separator(|)", "filters(packages)"}, 0, 
"|", Collections.singletonList("packages"));
     }
 
@@ -413,7 +415,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short}{separator(|)}{filters(packages)} }
      */
     @Test
-    public void testShortAndSeparatorAndFilters() {
+    void testShortAndSeparatorAndFilters() {
         test(
                 new String[] {"short", "separator(|)", "filters(packages)"},
                 2,
@@ -425,7 +427,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{10}{separator(|)}{filters(packages)} }
      */
     @Test
-    public void testDepthAndSeparatorAndFilters() {
+    void testDepthAndSeparatorAndFilters() {
         test(new String[] {"10", "separator(|)", "filters(packages)"}, 10, 
"|", Collections.singletonList("packages"));
     }
 
@@ -433,7 +435,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full,filters(packages)} }
      */
     @Test
-    public void testSingleOptionFullAndFilters() {
+    void testSingleOptionFullAndFilters() {
         test(
                 new String[] {"full,filters(packages)"},
                 Integer.MAX_VALUE,
@@ -445,7 +447,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none,filters(packages)} }
      */
     @Test
-    public void testSingleOptionNoneAndFilters() {
+    void testSingleOptionNoneAndFilters() {
         test(new String[] {"none,filters(packages)"}, 0, 
Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
     }
 
@@ -453,7 +455,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short,filters(packages)} }
      */
     @Test
-    public void testSingleOptionShortAndFilters() {
+    void testSingleOptionShortAndFilters() {
         test(
                 new String[] {"short,filters(packages)"},
                 2,
@@ -465,7 +467,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none,filters(packages)} }
      */
     @Test
-    public void testSingleOptionDepthAndFilters() {
+    void testSingleOptionDepthAndFilters() {
         test(new String[] {"10,filters(packages)"}, 10, 
Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
     }
 
@@ -473,7 +475,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full,filters(package1,package2)} }
      */
     @Test
-    public void testSingleOptionFullAndMultipleFilters() {
+    void testSingleOptionFullAndMultipleFilters() {
         test(
                 new String[] {"full,filters(package1,package2)"},
                 Integer.MAX_VALUE,
@@ -485,7 +487,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none,filters(package1,package2)} }
      */
     @Test
-    public void testSingleOptionNoneAndMultipleFilters() {
+    void testSingleOptionNoneAndMultipleFilters() {
         test(
                 new String[] {"none,filters(package1,package2)"},
                 0,
@@ -497,7 +499,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{short,filters(package1,package2)} }
      */
     @Test
-    public void testSingleOptionShortAndMultipleFilters() {
+    void testSingleOptionShortAndMultipleFilters() {
         test(
                 new String[] {"short,filters(package1,package2)"},
                 2,
@@ -509,7 +511,7 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{none,filters(package1,package2)} }
      */
     @Test
-    public void testSingleOptionDepthAndMultipleFilters() {
+    void testSingleOptionDepthAndMultipleFilters() {
         test(
                 new String[] {"10,filters(package1,package2)"},
                 10,
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
new file mode 100644
index 0000000000..0595f68533
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static 
org.assertj.core.presentation.HexadecimalRepresentation.HEXA_REPRESENTATION;
+
+import java.util.Collections;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class JAnsiTextRendererTest {
+
+    public static Stream<Arguments> testRendering() {
+        return Stream.of(
+                // Use style names
+                Arguments.of(
+                        "KeyStyle=white ValueStyle=cyan,bold",
+                        "@|KeyStyle key|@ = @|ValueStyle some value|@",
+                        "\u001b[37mkey\u001b[m = \u001b[36;1msome 
value\u001b[m"),
+                // Use AnsiEscape codes directly
+                Arguments.of(
+                        "",
+                        "@|white key|@ = @|cyan,bold some value|@",
+                        "\u001b[37mkey\u001b[m = \u001b[36;1msome 
value\u001b[m"),
+                // Return broken escapes as is
+                Arguments.of("", "Hello @|crazy|@ world!", "Hello @|crazy|@ 
world!"),
+                Arguments.of("", "Hello @|world!", "Hello @|world!"));
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void testRendering(final String format, final String text, final String 
expected) {
+        final JAnsiTextRenderer renderer = new JAnsiTextRenderer(new String[] 
{"ansi", format}, Collections.emptyMap());
+        final StringBuilder actual = new StringBuilder();
+        renderer.render(new StringBuilder(text), actual);
+        assertThat(actual.toString())
+                .as("Rendering text '%s'", text)
+                .withRepresentation(HEXA_REPRESENTATION)
+                .isEqualTo(expected);
+    }
+}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
similarity index 94%
rename from 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java
rename to 
log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
index 294355a173..51278a04d6 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
@@ -31,7 +31,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 @LoggerContextSource("log4j-message-ansi.xml")
-public class MessageJansiConverterTest {
+public class MessageAnsiConverterTest {
 
     private static final String EXPECTED =
             "\u001B[31;1mWarning!\u001B[m Pants on \u001B[31mfire!\u001B[m" + 
Strings.LINE_SEPARATOR;
@@ -47,7 +47,7 @@ public class MessageJansiConverterTest {
 
     @Test
     public void testReplacement() {
-        // See org.fusesource.jansi.AnsiRenderer
+        // See 
https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html
         logger.error("@|red,bold Warning!|@ Pants on @|red fire!|@");
 
         final List<String> msgs = app.getMessages();
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
index 71fb6fbc77..06ab681fed 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
@@ -47,7 +47,7 @@ public class MessageStyledConverterTest {
 
     @Test
     public void testReplacement() {
-        // See org.fusesource.jansi.AnsiRenderer
+        // See 
https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html
         logger.error("@|WarningStyle Warning!|@ Pants on @|WarningStyle 
fire!|@");
 
         final List<String> msgs = app.getMessages();
diff --git a/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml 
b/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml
deleted file mode 100644
index d30b0fb406..0000000000
--- a/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to you under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<Configuration status="OFF">
-  <Appenders>
-    <Console name="Console" target="SYSTEM_OUT">
-      <PatternLayout pattern="%style{%d}{white} %style{[%t]} 
%style{%-5level:}{yellow} %style{%msg{ansi}{KeyStyle=white 
ValueStyle=cyan,bold}%n%throwable}{green}" />
-    </Console>
-  </Appenders>
-  <Loggers>
-    <Logger name="org.foo" level="DEBUG" />
-    <Root level="TRACE">
-      <AppenderRef ref="Console" />
-    </Root>
-  </Loggers>
-</Configuration>
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index 1e35ebce72..f5693dc2e9 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -66,7 +66,6 @@
       org.apache.commons.csv;resolution:=optional,
       org.apache.kafka.*;resolution:=optional,
       org.codehaus.stax2;resolution:=optional,
-      org.fusesource.jansi;resolution:=optional,
       org.jctools.*;resolution:=optional,
       org.zeromq;resolution:=optional,
       javax.lang.model.*;resolution:=optional,
@@ -97,7 +96,6 @@
       java.management;transitive=false;static=true,
       java.naming;transitive=false,
       org.apache.commons.csv;transitive=false,
-      org.fusesource.jansi;transitive=false,
       org.jspecify;transitive=false,
       org.zeromq.jeromq;transitive=false,
       <!-- A module descriptor is only available in version 1.2.16+, hence it 
is not detected -->
@@ -194,12 +192,6 @@
       <artifactId>jackson-dataformat-yaml</artifactId>
       <optional>true</optional>
     </dependency>
-    <!-- Required for console color support in Windows -->
-    <dependency>
-      <groupId>org.fusesource.jansi</groupId>
-      <artifactId>jansi</artifactId>
-      <optional>true</optional>
-    </dependency>
     <!-- Alternative implementation of BlockingQueue using JCTools for 
AsyncAppender -->
     <dependency>
       <groupId>org.jctools</groupId>
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
index 986c82863f..1b1bf5e2bd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
@@ -20,10 +20,7 @@ import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.PrintStream;
 import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Constructor;
 import java.nio.charset.Charset;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.logging.log4j.core.Appender;
@@ -35,12 +32,8 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
 import 
org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
-import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.core.util.Booleans;
 import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
-import org.apache.logging.log4j.core.util.Loader;
-import org.apache.logging.log4j.core.util.Throwables;
-import org.apache.logging.log4j.util.Chars;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
 /**
@@ -61,8 +54,7 @@ import org.apache.logging.log4j.util.PropertiesUtil;
 public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputStreamManager> {
 
     public static final String PLUGIN_NAME = "Console";
-    private static final String JANSI_CLASS = 
"org.fusesource.jansi.WindowsAnsiOutputStream";
-    private static ConsoleManagerFactory factory = new ConsoleManagerFactory();
+    private static final ConsoleManagerFactory factory = new 
ConsoleManagerFactory();
     private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
     private static final AtomicInteger COUNT = new AtomicInteger();
 
@@ -116,10 +108,10 @@ public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputSt
      *
      * @param layout The layout to use (required).
      * @param filter The Filter or null.
-     * @param targetStr The target ("SYSTEM_OUT" or "SYSTEM_ERR"). The default 
is "SYSTEM_OUT".
+     * @param target The target ("SYSTEM_OUT" or "SYSTEM_ERR"). The default is 
"SYSTEM_OUT".
      * @param name The name of the Appender (required).
      * @param follow If true will follow changes to the underlying output 
stream.
-     * @param ignore If {@code "true"} (default) exceptions encountered when 
appending events are logged; otherwise they
+     * @param ignoreExceptions If {@code "true"} (default) exceptions 
encountered when appending events are logged; otherwise they
      *            are propagated to the caller.
      * @return The ConsoleAppender.
      * @deprecated Deprecated in 2.7; use {@link #newBuilder()}.
@@ -128,22 +120,18 @@ public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputSt
     public static ConsoleAppender createAppender(
             Layout<? extends Serializable> layout,
             final Filter filter,
-            final String targetStr,
+            final String target,
             final String name,
             final String follow,
-            final String ignore) {
-        if (name == null) {
-            LOGGER.error("No name provided for ConsoleAppender");
-            return null;
-        }
-        if (layout == null) {
-            layout = PatternLayout.createDefaultLayout();
-        }
-        final boolean isFollow = Boolean.parseBoolean(follow);
-        final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
-        final Target target = targetStr == null ? DEFAULT_TARGET : 
Target.valueOf(targetStr);
-        return new ConsoleAppender(
-                name, layout, filter, getManager(target, isFollow, false, 
layout), ignoreExceptions, target, null);
+            final String ignoreExceptions) {
+        return newBuilder()
+                .setLayout(layout)
+                .setFilter(filter)
+                .setTarget(target == null ? DEFAULT_TARGET : 
Target.valueOf(target))
+                .setName(name)
+                .setFollow(Boolean.parseBoolean(follow))
+                .setIgnoreExceptions(Booleans.parseBoolean(ignoreExceptions, 
true))
+                .build();
     }
 
     /**
@@ -171,21 +159,15 @@ public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputSt
             final boolean follow,
             final boolean direct,
             final boolean ignoreExceptions) {
-        // @formatter:on
-        if (name == null) {
-            LOGGER.error("No name provided for ConsoleAppender");
-            return null;
-        }
-        if (layout == null) {
-            layout = PatternLayout.createDefaultLayout();
-        }
-        target = target == null ? Target.SYSTEM_OUT : target;
-        if (follow && direct) {
-            LOGGER.error("Cannot use both follow and direct on 
ConsoleAppender");
-            return null;
-        }
-        return new ConsoleAppender(
-                name, layout, filter, getManager(target, follow, direct, 
layout), ignoreExceptions, target, null);
+        return newBuilder()
+                .setLayout(layout)
+                .setFilter(filter)
+                .setTarget(target)
+                .setName(name)
+                .setFollow(follow)
+                .setDirect(direct)
+                .setIgnoreExceptions(ignoreExceptions)
+                .build();
     }
 
     public static ConsoleAppender createDefaultAppenderForLayout(final 
Layout<? extends Serializable> layout) {
@@ -194,7 +176,7 @@ public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputSt
                 "DefaultConsole-" + COUNT.incrementAndGet(),
                 layout,
                 null,
-                getDefaultManager(DEFAULT_TARGET, false, false, layout),
+                getDefaultManager(layout),
                 true,
                 DEFAULT_TARGET,
                 null);
@@ -242,85 +224,42 @@ public final class ConsoleAppender extends 
AbstractOutputStreamAppender<OutputSt
             if (!isValid()) {
                 return null;
             }
-            if (follow && direct) {
-                throw new IllegalArgumentException(
-                        "Cannot use both follow and direct on ConsoleAppender 
'" + getName() + "'");
+            if (direct && follow) {
+                LOGGER.error("Cannot use both `direct` and `follow` on 
ConsoleAppender.");
+                return null;
             }
             final Layout<? extends Serializable> layout = 
getOrCreateLayout(target.getDefaultCharset());
+
+            OutputStream stream = direct
+                    ? getDirectOutputStream(target)
+                    : follow ? getFollowOutputStream(target) : 
getDefaultOutputStream(target);
+
+            final String managerName = target.name() + '.' + follow + '.' + 
direct;
+            final OutputStreamManager manager =
+                    OutputStreamManager.getManager(managerName, new 
FactoryData(stream, managerName, layout), factory);
             return new ConsoleAppender(
-                    getName(),
-                    layout,
-                    getFilter(),
-                    getManager(target, follow, direct, layout),
-                    isIgnoreExceptions(),
-                    target,
-                    getPropertyArray());
+                    getName(), layout, getFilter(), manager, 
isIgnoreExceptions(), target, getPropertyArray());
         }
     }
 
-    private static OutputStreamManager getDefaultManager(
-            final Target target,
-            final boolean follow,
-            final boolean direct,
-            final Layout<? extends Serializable> layout) {
-        final OutputStream os = getOutputStream(follow, direct, target);
-
+    private static OutputStreamManager getDefaultManager(final Layout<? 
extends Serializable> layout) {
+        final OutputStream os = 
getDefaultOutputStream(ConsoleAppender.DEFAULT_TARGET);
         // LOG4J2-1176 DefaultConfiguration should not share 
OutputStreamManager instances to avoid memory leaks.
-        final String managerName = target.name() + '.' + follow + '.' + direct 
+ "-" + COUNT.get();
+        final String managerName = ConsoleAppender.DEFAULT_TARGET.name() + 
".false.false-" + COUNT.get();
         return OutputStreamManager.getManager(managerName, new FactoryData(os, 
managerName, layout), factory);
     }
 
-    private static OutputStreamManager getManager(
-            final Target target,
-            final boolean follow,
-            final boolean direct,
-            final Layout<? extends Serializable> layout) {
-        final OutputStream os = getOutputStream(follow, direct, target);
-        final String managerName = target.name() + '.' + follow + '.' + direct;
-        return OutputStreamManager.getManager(managerName, new FactoryData(os, 
managerName, layout), factory);
+    private static OutputStream getDefaultOutputStream(Target target) {
+        return new CloseShieldOutputStream(target == Target.SYSTEM_OUT ? 
System.out : System.err);
     }
 
-    private static OutputStream getOutputStream(final boolean follow, final 
boolean direct, final Target target) {
-        final String enc = Charset.defaultCharset().name();
-        OutputStream outputStream;
-        try {
-            // @formatter:off
-            outputStream = target == Target.SYSTEM_OUT
-                    ? direct
-                            ? new FileOutputStream(FileDescriptor.out)
-                            : (follow ? new PrintStream(new SystemOutStream(), 
true, enc) : System.out)
-                    : direct
-                            ? new FileOutputStream(FileDescriptor.err)
-                            : (follow ? new PrintStream(new SystemErrStream(), 
true, enc) : System.err);
-            // @formatter:on
-            outputStream = new CloseShieldOutputStream(outputStream);
-        } catch (final UnsupportedEncodingException ex) { // should never 
happen
-            throw new IllegalStateException("Unsupported default encoding " + 
enc, ex);
-        }
-        final PropertiesUtil propsUtil = PropertiesUtil.getProperties();
-        if (!propsUtil.isOsWindows() || 
propsUtil.getBooleanProperty("log4j.skipJansi", true) || direct) {
-            return outputStream;
-        }
-        try {
-            // We type the parameter as a wildcard to avoid a hard reference 
to Jansi.
-            final Class<?> clazz = Loader.loadClass(JANSI_CLASS);
-            final Constructor<?> constructor = 
clazz.getConstructor(OutputStream.class);
-            return new CloseShieldOutputStream((OutputStream) 
constructor.newInstance(outputStream));
-        } catch (final ClassNotFoundException cnfe) {
-            LOGGER.debug("Jansi is not installed, cannot find {}", 
JANSI_CLASS);
-        } catch (final NoSuchMethodException nsme) {
-            LOGGER.warn("{} is missing the proper constructor", JANSI_CLASS);
-        } catch (final Exception ex) {
-            LOGGER.warn(
-                    "Unable to instantiate {} due to {}",
-                    JANSI_CLASS,
-                    clean(Throwables.getRootCause(ex).toString()).trim());
-        }
-        return outputStream;
+    private static OutputStream getDirectOutputStream(Target target) {
+        return new CloseShieldOutputStream(
+                new FileOutputStream(target == Target.SYSTEM_OUT ? 
FileDescriptor.out : FileDescriptor.err));
     }
 
-    private static String clean(final String string) {
-        return string.replace(Chars.NUL, Chars.SPACE);
+    private static OutputStream getFollowOutputStream(Target target) {
+        return target == Target.SYSTEM_OUT ? new SystemOutStream() : new 
SystemErrStream();
     }
 
     /**
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
index 5df74e5d9c..74bc937ab6 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
@@ -23,9 +23,7 @@ import 
org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
 import org.apache.logging.log4j.core.pattern.TextRenderer;
 import org.apache.logging.log4j.core.util.Integers;
-import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.core.util.Patterns;
-import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Strings;
 
 /**
@@ -290,17 +288,11 @@ public final class ThrowableFormatOptions {
                         || option.equalsIgnoreCase(LOCALIZED_MESSAGE)) {
                     lines = 2;
                 } else if (option.startsWith("ansi(") && option.endsWith(")") 
|| option.equals("ansi")) {
-                    if (Loader.isJansiAvailable()) {
-                        final String styleMapStr = option.equals("ansi")
-                                ? Strings.EMPTY
-                                : option.substring("ansi(".length(), 
option.length() - 1);
-                        ansiRenderer = new JAnsiTextRenderer(
-                                new String[] {null, styleMapStr}, 
JAnsiTextRenderer.DefaultExceptionStyleMap);
-                    } else {
-                        StatusLogger.getLogger()
-                                .warn(
-                                        "You requested ANSI exception 
rendering but JANSI is not on the classpath. Please see 
https://logging.apache.org/log4j/2.x/runtime-dependencies.html";);
-                    }
+                    final String styleMapStr = option.equals("ansi")
+                            ? Strings.EMPTY
+                            : option.substring("ansi(".length(), 
option.length() - 1);
+                    ansiRenderer = new JAnsiTextRenderer(
+                            new String[] {null, styleMapStr}, 
JAnsiTextRenderer.DefaultExceptionStyleMap);
                 } else if (option.startsWith("S(") && option.endsWith(")")) {
                     suffix = option.substring("S(".length(), option.length() - 
1);
                 } else if (option.startsWith("suffix(") && 
option.endsWith(")")) {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
index 2d4bdcd199..666e8325ed 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
@@ -18,7 +18,7 @@
  * Log4j 2 private implementation classes.
  */
 @Export
-@Version("2.25.0")
+@Version("2.24.1")
 package org.apache.logging.log4j.core.impl;
 
 import org.osgi.annotation.bundle.Export;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
index a915cdadfb..5f6e429927 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
@@ -38,7 +38,6 @@ import 
org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
 import org.apache.logging.log4j.core.pattern.PatternFormatter;
 import org.apache.logging.log4j.core.pattern.PatternParser;
 import org.apache.logging.log4j.core.pattern.RegexReplacement;
-import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.Strings;
 
 /**
@@ -652,7 +651,7 @@ public final class PatternLayout extends 
AbstractStringLayout {
         private boolean alwaysWriteExceptions = true;
 
         @PluginBuilderAttribute
-        private boolean disableAnsi = !useAnsiEscapeCodes();
+        private boolean disableAnsi;
 
         @PluginBuilderAttribute
         private boolean noConsoleNoAnsi;
@@ -665,13 +664,6 @@ public final class PatternLayout extends 
AbstractStringLayout {
 
         private Builder() {}
 
-        private boolean useAnsiEscapeCodes() {
-            final PropertiesUtil propertiesUtil = 
PropertiesUtil.getProperties();
-            final boolean isPlatformSupportsAnsi = 
!propertiesUtil.isOsWindows();
-            final boolean isJansiRequested = 
!propertiesUtil.getBooleanProperty("log4j.skipJansi", true);
-            return isPlatformSupportsAnsi || isJansiRequested;
-        }
-
         /**
          * @param pattern
          *        The pattern. If not specified, defaults to 
DEFAULT_CONVERSION_PATTERN.
@@ -731,8 +723,7 @@ public final class PatternLayout extends 
AbstractStringLayout {
 
         /**
          * @param disableAnsi
-         *        If {@code "true"} (default is value of system property 
`log4j.skipJansi`, or `true` if undefined),
-         *        do not output ANSI escape codes
+         *        If {@code true}, do not output ANSI escape codes.
          */
         public Builder withDisableAnsi(final boolean disableAnsi) {
             this.disableAnsi = disableAnsi;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index 74633b10a1..34213373df 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -421,6 +421,11 @@ public enum AnsiEscape {
      * @return a new map
      */
     public static Map<String, String> createMap(final String[] values, final 
String[] dontEscapeKeys) {
+        return createMap(values, dontEscapeKeys, "\\s");
+    }
+
+    static Map<String, String> createMap(
+            final String[] values, final String[] dontEscapeKeys, final String 
separatorRegex) {
         final String[] sortedIgnoreKeys = dontEscapeKeys != null ? 
dontEscapeKeys.clone() : Strings.EMPTY_ARRAY;
         Arrays.sort(sortedIgnoreKeys);
         final Map<String, String> map = new HashMap<>();
@@ -430,7 +435,7 @@ public enum AnsiEscape {
                 final String key = toRootUpperCase(keyValue[0]);
                 final String value = keyValue[1];
                 final boolean escape = Arrays.binarySearch(sortedIgnoreKeys, 
key) < 0;
-                map.put(key, escape ? createSequence(value.split("\\s")) : 
value);
+                map.put(key, escape ? 
createSequence(value.split(separatorRegex)) : value);
             } else {
                 LOGGER.warn("Syntax error, missing '=': Expected 
\"{KEY1=VALUE, KEY2=VALUE, ...}");
             }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
index b952957345..072dfeb87f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
@@ -16,28 +16,31 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.BG_RED;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.BOLD;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.RED;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.WHITE;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.YELLOW;
 import static org.apache.logging.log4j.util.Strings.toRootUpperCase;
-import static org.fusesource.jansi.AnsiRenderer.Code.BG_RED;
-import static org.fusesource.jansi.AnsiRenderer.Code.BOLD;
-import static org.fusesource.jansi.AnsiRenderer.Code.RED;
-import static org.fusesource.jansi.AnsiRenderer.Code.WHITE;
-import static org.fusesource.jansi.AnsiRenderer.Code.YELLOW;
 
+import java.util.AbstractMap;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
+import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.AnsiRenderer;
-import org.fusesource.jansi.AnsiRenderer.Code;
 
 /**
  * Renders an input as ANSI escaped output.
- *
- * Uses the JAnsi rendering syntax as the default to render a message into an 
ANSI escaped string.
- *
+ * <p>
+ * Uses the
+ * <a 
href="https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html";>JLine
 AnsiRenderer syntax</a>
+ * to render a message into an ANSI escaped string.
+ * </p>
+ * <p>
  * The default syntax for embedded ANSI codes is:
- *
+ * </p>
  * <pre>
  *   &#64;|<em>code</em>(,<em>code</em>)* <em>text</em>|@
  * </pre>
@@ -72,279 +75,245 @@ import org.fusesource.jansi.AnsiRenderer.Code;
  * logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), 
entry.getValue());
  * </pre>
  *
- * Note: This class originally copied and then heavily modified code from 
JAnsi's AnsiRenderer (which is licensed as
- * Apache 2.0.)
- *
- * @see AnsiRenderer
+ * <p>
+ *     <strong>Note:</strong> this class was originally copied and then 
heavily modified from
+ *     <a 
href="https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html";>JAnsi/JLine
 AnsiRenderer</a>,
+ *     licensed under an Apache Software License, version 2.0.
+ * </p>
  */
 public final class JAnsiTextRenderer implements TextRenderer {
 
-    public static final Map<String, Code[]> DefaultExceptionStyleMap;
-    static final Map<String, Code[]> DefaultMessageStyleMap;
-    private static final Map<String, Map<String, Code[]>> PrefedinedStyleMaps;
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    public static final Map<String, String> DefaultExceptionStyleMap;
+    static final Map<String, String> DEFAULT_MESSAGE_STYLE_MAP;
+    private static final Map<String, Map<String, String>> 
PREFEDINED_STYLE_MAPS;
 
-    private static void put(final Map<String, Code[]> map, final String name, 
final Code... codes) {
-        map.put(name, codes);
+    private static final String BEGIN_TOKEN = "@|";
+    private static final String END_TOKEN = "|@";
+    // The length of AnsiEscape.CSI
+    private static final int CSI_LENGTH = 2;
+
+    private static Map.Entry<String, String> entry(final String name, final 
AnsiEscape... codes) {
+        final StringBuilder sb = new StringBuilder(AnsiEscape.CSI.getCode());
+        for (final AnsiEscape code : codes) {
+            sb.append(code.getCode());
+        }
+        return new AbstractMap.SimpleImmutableEntry<>(name, sb.toString());
+    }
+
+    @SafeVarargs
+    private static <V> Map<String, V> ofEntries(final Map.Entry<String, V>... 
entries) {
+        final Map<String, V> map = new HashMap<>(entries.length);
+        for (final Map.Entry<String, V> entry : entries) {
+            map.put(entry.getKey(), entry.getValue());
+        }
+        return Collections.unmodifiableMap(map);
     }
 
     static {
-        final Map<String, Map<String, Code[]>> tempPreDefs = new HashMap<>();
         // Default style: Spock
-        {
-            // TODO Should the keys be in an enum?
-            final Map<String, Code[]> map = new HashMap<>();
-            put(map, "Prefix", WHITE);
-            put(map, "Name", BG_RED, WHITE);
-            put(map, "NameMessageSeparator", BG_RED, WHITE);
-            put(map, "Message", BG_RED, WHITE, BOLD);
-            put(map, "At", WHITE);
-            put(map, "CauseLabel", WHITE);
-            put(map, "Text", WHITE);
-            put(map, "More", WHITE);
-            put(map, "Suppressed", WHITE);
-            // StackTraceElement
-            put(map, "StackTraceElement.ClassLoaderName", WHITE);
-            put(map, "StackTraceElement.ClassLoaderSeparator", WHITE);
-            put(map, "StackTraceElement.ModuleName", WHITE);
-            put(map, "StackTraceElement.ModuleVersionSeparator", WHITE);
-            put(map, "StackTraceElement.ModuleVersion", WHITE);
-            put(map, "StackTraceElement.ModuleNameSeparator", WHITE);
-            put(map, "StackTraceElement.ClassName", YELLOW);
-            put(map, "StackTraceElement.ClassMethodSeparator", YELLOW);
-            put(map, "StackTraceElement.MethodName", YELLOW);
-            put(map, "StackTraceElement.NativeMethod", YELLOW);
-            put(map, "StackTraceElement.FileName", RED);
-            put(map, "StackTraceElement.LineNumber", RED);
-            put(map, "StackTraceElement.Container", RED);
-            put(map, "StackTraceElement.ContainerSeparator", WHITE);
-            put(map, "StackTraceElement.UnknownSource", RED);
-            // ExtraClassInfo
-            put(map, "ExtraClassInfo.Inexact", YELLOW);
-            put(map, "ExtraClassInfo.Container", YELLOW);
-            put(map, "ExtraClassInfo.ContainerSeparator", YELLOW);
-            put(map, "ExtraClassInfo.Location", YELLOW);
-            put(map, "ExtraClassInfo.Version", YELLOW);
-            // Save
-            DefaultExceptionStyleMap = Collections.unmodifiableMap(map);
-            tempPreDefs.put("Spock", DefaultExceptionStyleMap);
-        }
+        final Map<String, String> spock = ofEntries(
+                entry("Prefix", WHITE),
+                entry("Name", BG_RED, WHITE),
+                entry("NameMessageSeparator", BG_RED, WHITE),
+                entry("Message", BG_RED, WHITE, BOLD),
+                entry("At", WHITE),
+                entry("CauseLabel", WHITE),
+                entry("Text", WHITE),
+                entry("More", WHITE),
+                entry("Suppressed", WHITE),
+                // StackTraceElement
+                entry("StackTraceElement.ClassLoaderName", WHITE),
+                entry("StackTraceElement.ClassLoaderSeparator", WHITE),
+                entry("StackTraceElement.ModuleName", WHITE),
+                entry("StackTraceElement.ModuleVersionSeparator", WHITE),
+                entry("StackTraceElement.ModuleVersion", WHITE),
+                entry("StackTraceElement.ModuleNameSeparator", WHITE),
+                entry("StackTraceElement.ClassName", YELLOW),
+                entry("StackTraceElement.ClassMethodSeparator", YELLOW),
+                entry("StackTraceElement.MethodName", YELLOW),
+                entry("StackTraceElement.NativeMethod", YELLOW),
+                entry("StackTraceElement.FileName", RED),
+                entry("StackTraceElement.LineNumber", RED),
+                entry("StackTraceElement.Container", RED),
+                entry("StackTraceElement.ContainerSeparator", WHITE),
+                entry("StackTraceElement.UnknownSource", RED),
+                // ExtraClassInfo
+                entry("ExtraClassInfo.Inexact", YELLOW),
+                entry("ExtraClassInfo.Container", YELLOW),
+                entry("ExtraClassInfo.ContainerSeparator", YELLOW),
+                entry("ExtraClassInfo.Location", YELLOW),
+                entry("ExtraClassInfo.Version", YELLOW));
+
         // Style: Kirk
-        {
-            // TODO Should the keys be in an enum?
-            final Map<String, Code[]> map = new HashMap<>();
-            put(map, "Prefix", WHITE);
-            put(map, "Name", BG_RED, YELLOW, BOLD);
-            put(map, "NameMessageSeparator", BG_RED, YELLOW);
-            put(map, "Message", BG_RED, WHITE, BOLD);
-            put(map, "At", WHITE);
-            put(map, "CauseLabel", WHITE);
-            put(map, "Text", WHITE);
-            put(map, "More", WHITE);
-            put(map, "Suppressed", WHITE);
-            // StackTraceElement
-            put(map, "StackTraceElement.ClassLoaderName", WHITE);
-            put(map, "StackTraceElement.ClassLoaderSeparator", WHITE);
-            put(map, "StackTraceElement.ModuleName", WHITE);
-            put(map, "StackTraceElement.ModuleVersionSeparator", WHITE);
-            put(map, "StackTraceElement.ModuleVersion", WHITE);
-            put(map, "StackTraceElement.ModuleNameSeparator", WHITE);
-            put(map, "StackTraceElement.ClassName", BG_RED, WHITE);
-            put(map, "StackTraceElement.ClassMethodSeparator", BG_RED, YELLOW);
-            put(map, "StackTraceElement.MethodName", BG_RED, YELLOW);
-            put(map, "StackTraceElement.NativeMethod", BG_RED, YELLOW);
-            put(map, "StackTraceElement.FileName", RED);
-            put(map, "StackTraceElement.LineNumber", RED);
-            put(map, "StackTraceElement.Container", RED);
-            put(map, "StackTraceElement.ContainerSeparator", WHITE);
-            put(map, "StackTraceElement.UnknownSource", RED);
-            // ExtraClassInfo
-            put(map, "ExtraClassInfo.Inexact", YELLOW);
-            put(map, "ExtraClassInfo.Container", WHITE);
-            put(map, "ExtraClassInfo.ContainerSeparator", WHITE);
-            put(map, "ExtraClassInfo.Location", YELLOW);
-            put(map, "ExtraClassInfo.Version", YELLOW);
-            // Save
-            tempPreDefs.put("Kirk", Collections.unmodifiableMap(map));
-        }
-        {
-            final Map<String, Code[]> temp = new HashMap<>();
-            // TODO
-            DefaultMessageStyleMap = Collections.unmodifiableMap(temp);
-        }
-        PrefedinedStyleMaps = Collections.unmodifiableMap(tempPreDefs);
+        final Map<String, String> kirk = ofEntries(
+                entry("Prefix", WHITE),
+                entry("Name", BG_RED, YELLOW, BOLD),
+                entry("NameMessageSeparator", BG_RED, YELLOW),
+                entry("Message", BG_RED, WHITE, BOLD),
+                entry("At", WHITE),
+                entry("CauseLabel", WHITE),
+                entry("Text", WHITE),
+                entry("More", WHITE),
+                entry("Suppressed", WHITE),
+                // StackTraceElement
+                entry("StackTraceElement.ClassLoaderName", WHITE),
+                entry("StackTraceElement.ClassLoaderSeparator", WHITE),
+                entry("StackTraceElement.ModuleName", WHITE),
+                entry("StackTraceElement.ModuleVersionSeparator", WHITE),
+                entry("StackTraceElement.ModuleVersion", WHITE),
+                entry("StackTraceElement.ModuleNameSeparator", WHITE),
+                entry("StackTraceElement.ClassName", BG_RED, WHITE),
+                entry("StackTraceElement.ClassMethodSeparator", BG_RED, 
YELLOW),
+                entry("StackTraceElement.MethodName", BG_RED, YELLOW),
+                entry("StackTraceElement.NativeMethod", BG_RED, YELLOW),
+                entry("StackTraceElement.FileName", RED),
+                entry("StackTraceElement.LineNumber", RED),
+                entry("StackTraceElement.Container", RED),
+                entry("StackTraceElement.ContainerSeparator", WHITE),
+                entry("StackTraceElement.UnknownSource", RED),
+                // ExtraClassInfo
+                entry("ExtraClassInfo.Inexact", YELLOW),
+                entry("ExtraClassInfo.Container", WHITE),
+                entry("ExtraClassInfo.ContainerSeparator", WHITE),
+                entry("ExtraClassInfo.Location", YELLOW),
+                entry("ExtraClassInfo.Version", YELLOW));
+
+        // Save
+        DefaultExceptionStyleMap = spock;
+        DEFAULT_MESSAGE_STYLE_MAP = Collections.emptyMap();
+        Map<String, Map<String, String>> predefinedStyleMaps = new HashMap<>();
+        predefinedStyleMaps.put("Spock", spock);
+        predefinedStyleMaps.put("Kirk", kirk);
+        PREFEDINED_STYLE_MAPS = 
Collections.unmodifiableMap(predefinedStyleMaps);
     }
 
     private final String beginToken;
     private final int beginTokenLen;
     private final String endToken;
     private final int endTokenLen;
-    private final Map<String, Code[]> styleMap;
+    private final Map<String, String> styleMap;
 
-    public JAnsiTextRenderer(final String[] formats, final Map<String, Code[]> 
defaultStyleMap) {
-        String tempBeginToken = AnsiRenderer.BEGIN_TOKEN;
-        String tempEndToken = AnsiRenderer.END_TOKEN;
-        final Map<String, Code[]> map;
+    public JAnsiTextRenderer(final String[] formats, final Map<String, String> 
defaultStyleMap) {
+        // The format string is a list of whitespace-separated expressions:
+        // Key=AnsiEscape(,AnsiEscape)*
         if (formats.length > 1) {
-            final String allStylesStr = formats[1];
-            // Style def split
-            final String[] allStyleAssignmentsArr = allStylesStr.split(" ");
-            map = new HashMap<>(allStyleAssignmentsArr.length + 
defaultStyleMap.size());
-            map.putAll(defaultStyleMap);
-            for (final String styleAssignmentStr : allStyleAssignmentsArr) {
-                final String[] styleAssignmentArr = 
styleAssignmentStr.split("=");
-                if (styleAssignmentArr.length != 2) {
-                    StatusLogger.getLogger()
-                            .warn(
-                                    "{} parsing style \"{}\", expected format: 
StyleName=Code(,Code)*",
-                                    getClass().getSimpleName(),
-                                    styleAssignmentStr);
+            final String stylesStr = formats[1];
+            final Map<String, String> map = AnsiEscape.createMap(
+                    stylesStr.split("\\s", -1), new String[] {"BeginToken", 
"EndToken", "Style"}, ",");
+
+            // Handle the special tokens
+            beginToken = Objects.toString(map.remove("BeginToken"), 
BEGIN_TOKEN);
+            endToken = Objects.toString(map.remove("EndToken"), END_TOKEN);
+            final String predefinedStyle = map.remove("Style");
+
+            // Create style map
+            final Map<String, String> styleMap = new HashMap<>(map.size() + 
defaultStyleMap.size());
+            defaultStyleMap.forEach((k, v) -> styleMap.put(toRootUpperCase(k), 
v));
+            if (predefinedStyle != null) {
+                final Map<String, String> predefinedMap = 
PREFEDINED_STYLE_MAPS.get(predefinedStyle);
+                if (predefinedMap != null) {
+                    map.putAll(predefinedMap);
                 } else {
-                    final String styleName = styleAssignmentArr[0];
-                    final String codeListStr = styleAssignmentArr[1];
-                    final String[] codeNames = codeListStr.split(",");
-                    if (codeNames.length == 0) {
-                        StatusLogger.getLogger()
-                                .warn(
-                                        "{} parsing style \"{}\", expected 
format: StyleName=Code(,Code)*",
-                                        getClass().getSimpleName(),
-                                        styleAssignmentStr);
-                    } else {
-                        switch (styleName) {
-                            case "BeginToken":
-                                tempBeginToken = codeNames[0];
-                                break;
-                            case "EndToken":
-                                tempEndToken = codeNames[0];
-                                break;
-                            case "StyleMapName":
-                                final String predefinedMapName = codeNames[0];
-                                final Map<String, Code[]> predefinedMap = 
PrefedinedStyleMaps.get(predefinedMapName);
-                                if (predefinedMap != null) {
-                                    map.putAll(predefinedMap);
-                                } else {
-                                    StatusLogger.getLogger()
-                                            .warn(
-                                                    "Unknown predefined map 
name {}, pick one of {}",
-                                                    predefinedMapName,
-                                                    null);
-                                }
-                                break;
-                            default:
-                                final Code[] codes = new 
Code[codeNames.length];
-                                for (int i = 0; i < codes.length; i++) {
-                                    codes[i] = toCode(codeNames[i]);
-                                }
-                                map.put(styleName, codes);
-                        }
-                    }
+                    LOGGER.warn(
+                            "Unknown predefined map name {}, pick one of {}",
+                            predefinedStyle,
+                            PREFEDINED_STYLE_MAPS.keySet());
                 }
             }
+            styleMap.putAll(map);
+            this.styleMap = Collections.unmodifiableMap(styleMap);
         } else {
-            map = defaultStyleMap;
-        }
-        styleMap = map;
-        beginToken = tempBeginToken;
-        endToken = tempEndToken;
-        beginTokenLen = tempBeginToken.length();
-        endTokenLen = tempEndToken.length();
-    }
-
-    public Map<String, Code[]> getStyleMap() {
-        return styleMap;
-    }
-
-    private void render(final Ansi ansi, final Code code) {
-        if (code.isColor()) {
-            if (code.isBackground()) {
-                ansi.bg(code.getColor());
-            } else {
-                ansi.fg(code.getColor());
-            }
-        } else if (code.isAttribute()) {
-            ansi.a(code.getAttribute());
-        }
-    }
-
-    private void render(final Ansi ansi, final Code... codes) {
-        for (final Code code : codes) {
-            render(ansi, code);
+            beginToken = BEGIN_TOKEN;
+            endToken = END_TOKEN;
+            this.styleMap = Collections.unmodifiableMap(defaultStyleMap);
         }
+        beginTokenLen = beginToken.length();
+        endTokenLen = endToken.length();
     }
 
     /**
-     * Renders the given text with the given names which can be ANSI code 
names or Log4j style names.
+     * Renders the given input with the given names which can be ANSI code 
names or Log4j style names.
      *
-     * @param text
-     *            The text to render
-     * @param names
+     * @param input
+     *            The input to render
+     * @param styleNames
      *            ANSI code names or Log4j style names.
-     * @return A rendered string containing ANSI codes.
      */
-    private String render(final String text, final String... names) {
-        final Ansi ansi = Ansi.ansi();
-        for (final String name : names) {
-            final Code[] codes = styleMap.get(name);
-            if (codes != null) {
-                render(ansi, codes);
+    private void render(final String input, final StringBuilder output, final 
String... styleNames) {
+        boolean first = true;
+        for (final String styleName : styleNames) {
+            final String escape = styleMap.get(toRootUpperCase(styleName));
+            if (escape != null) {
+                merge(escape, output, first);
             } else {
-                render(ansi, toCode(name));
+                merge(AnsiEscape.createSequence(styleName), output, first);
             }
+            first = false;
+        }
+        output.append(input).append(AnsiEscape.getDefaultStyle());
+    }
+
+    private static void merge(final String escapeSequence, final StringBuilder 
output, final boolean first) {
+        if (first) {
+            output.append(escapeSequence);
+        } else {
+            // Delete the trailing AnsiEscape.SUFFIX
+            output.setLength(output.length() - 1);
+            output.append(AnsiEscape.SEPARATOR.getCode());
+            output.append(escapeSequence.substring(CSI_LENGTH));
         }
-        return ansi.a(text).reset().toString();
     }
 
     // EXACT COPY OF StringBuilder version of the method but typed as String 
for input
     @Override
     public void render(final String input, final StringBuilder output, final 
String styleName)
             throws IllegalArgumentException {
-        output.append(render(input, styleName));
+        render(input, output, styleName.split(",", -1));
     }
 
     @Override
     public void render(final StringBuilder input, final StringBuilder output) 
throws IllegalArgumentException {
-        int i = 0;
-        int j, k;
+        int pos = 0;
+        int beginTokenPos, endTokenPos;
 
         while (true) {
-            j = input.indexOf(beginToken, i);
-            if (j == -1) {
-                if (i == 0) {
-                    output.append(input);
-                    return;
-                }
-                output.append(input.substring(i, input.length()));
+            beginTokenPos = input.indexOf(beginToken, pos);
+            if (beginTokenPos == -1) {
+                output.append(pos == 0 ? input : input.substring(pos, 
input.length()));
                 return;
             }
-            output.append(input.substring(i, j));
-            k = input.indexOf(endToken, j);
+            output.append(input.substring(pos, beginTokenPos));
+            endTokenPos = input.indexOf(endToken, beginTokenPos);
 
-            if (k == -1) {
-                output.append(input);
+            if (endTokenPos == -1) {
+                LOGGER.warn(
+                        "Missing matching end token {} for token at position 
{}: '{}'", endToken, beginTokenPos, input);
+                output.append(beginTokenPos == 0 ? input : 
input.substring(beginTokenPos, input.length()));
                 return;
             }
-            j += beginTokenLen;
-            final String spec = input.substring(j, k);
+            beginTokenPos += beginTokenLen;
+            final String spec = input.substring(beginTokenPos, endTokenPos);
 
-            final String[] items = 
spec.split(AnsiRenderer.CODE_TEXT_SEPARATOR, 2);
+            final String[] items = spec.split("\\s", 2);
             if (items.length == 1) {
-                output.append(input);
-                return;
+                LOGGER.warn("Missing argument in ANSI escape specification 
'{}'", spec);
+                output.append(beginToken).append(spec).append(endToken);
+            } else {
+                render(items[1], output, items[0].split(",", -1));
             }
-            final String replacement = render(items[1], items[0].split(","));
-
-            output.append(replacement);
-
-            i = k + endTokenLen;
+            pos = endTokenPos + endTokenLen;
         }
     }
 
-    private Code toCode(final String name) {
-        return Code.valueOf(toRootUpperCase(name));
+    public Map<String, String> getStyleMap() {
+        return styleMap;
     }
 
     @Override
     public String toString() {
-        return "JAnsiMessageRenderer [beginToken=" + beginToken + ", 
beginTokenLen=" + beginTokenLen + ", endToken="
+        return "AnsiMessageRenderer [beginToken=" + beginToken + ", 
beginTokenLen=" + beginTokenLen + ", endToken="
                 + endToken + ", endTokenLen=" + endTokenLen + ", styleMap=" + 
styleMap + "]";
     }
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
index 44016664af..dd7df75faf 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
@@ -23,10 +23,8 @@ import java.util.List;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.MultiformatMessage;
-import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.MultiFormatStringBuilderFormattable;
 import org.apache.logging.log4j.util.PerformanceSensitive;
 import org.apache.logging.log4j.util.StringBuilderFormattable;
@@ -52,12 +50,7 @@ public class MessagePatternConverter extends 
LogEventPatternConverter {
             for (final String option : options) {
                 switch (toRootUpperCase(option)) {
                     case "ANSI":
-                        if (Loader.isJansiAvailable()) {
-                            return new JAnsiTextRenderer(options, 
JAnsiTextRenderer.DefaultMessageStyleMap);
-                        }
-                        StatusLogger.getLogger()
-                                .warn("You requested ANSI message rendering 
but JANSI is not on the classpath.");
-                        return null;
+                        return new JAnsiTextRenderer(options, 
JAnsiTextRenderer.DEFAULT_MESSAGE_STYLE_MAP);
                     case "HTML":
                         return new HtmlTextRenderer(options);
                 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
index 5c047848b5..ac6407f47b 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
@@ -18,7 +18,7 @@
  * Provides classes implementing format specifiers in conversion patterns.
  */
 @Export
-@Version("2.25.0")
+@Version("2.24.1")
 package org.apache.logging.log4j.core.pattern;
 
 import org.osgi.annotation.bundle.Export;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
index 64ee6be359..4ae5d46335 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
@@ -349,6 +349,10 @@ public final class Loader {
         }
     }
 
+    /**
+     * @deprecated Since 2.25.0 without a replacement.
+     */
+    @Deprecated
     public static boolean isJansiAvailable() {
         return isClassAvailable("org.fusesource.jansi.AnsiRenderer");
     }
diff --git 
a/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
 
b/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
index 0dbd426d30..f460c5c607 100644
--- 
a/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
+++ 
b/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
@@ -16,8 +16,8 @@
  */
 package org.apache.logging.log4j.smtp;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.util.Iterator;
 import org.apache.logging.log4j.ThreadContext;
diff --git a/log4j-parent/pom.xml b/log4j-parent/pom.xml
index 4c82d04e14..3ae996ef97 100644
--- a/log4j-parent/pom.xml
+++ b/log4j-parent/pom.xml
@@ -100,7 +100,6 @@
     <javax-persistence.version>2.2</javax-persistence.version>
     <javax-servlet.version>4.0.1</javax-servlet.version>
     <javax-servlet-jsp.version>2.3.3</javax-servlet-jsp.version>
-    <jansi.version>2.4.1</jansi.version>
     
<java-allocation-instrumenter.version>3.3.4</java-allocation-instrumenter.version>
     <jazzer.version>0.22.1</jazzer.version>
     <jconsole.version>1.7.0</jconsole.version>
@@ -471,12 +470,6 @@
         <version>${jakarta-mail.version}</version>
       </dependency>
 
-      <dependency>
-        <groupId>org.fusesource.jansi</groupId>
-        <artifactId>jansi</artifactId>
-        <version>${jansi.version}</version>
-      </dependency>
-
       <!-- Used for garbage-free tests: -->
       <dependency>
         <groupId>com.google.code.java-allocation-instrumenter</groupId>
diff --git a/pom.xml b/pom.xml
index 03760b9eb0..88bf7db62f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -345,7 +345,6 @@
     <site-disruptor.version>4.0.0</site-disruptor.version>
     <site-flume.version>1.11.0</site-flume.version>
     <site-jackson.version>2.18.0</site-jackson.version>
-    <site-jansi.version>1.18</site-jansi.version>
     <site-javax-mail.version>1.6.2</site-javax-mail.version>
     <site-jctools.version>4.0.5</site-jctools.version>
     <site-je.version>18.3.12</site-je.version>
@@ -769,12 +768,6 @@
             <type>pom</type>
           </dependency>
 
-          <dependency>
-            <groupId>org.fusesource.jansi</groupId>
-            <artifactId>jansi</artifactId>
-            <version>${site-jansi.version}</version>
-          </dependency>
-
           <dependency>
             <groupId>com.sun.mail</groupId>
             <artifactId>javax.mail</artifactId>
diff --git a/src/changelog/.2.x.x/.release-notes.adoc.ftl 
b/src/changelog/.2.x.x/.release-notes.adoc.ftl
index 16be1ddfc7..47b4447337 100644
--- a/src/changelog/.2.x.x/.release-notes.adoc.ftl
+++ b/src/changelog/.2.x.x/.release-notes.adoc.ftl
@@ -38,4 +38,10 @@ This effectively helped with fixing some bugs by matching 
the feature parity of
 Additionally, rendered stack traces are ensured to be prefixed with a newline, 
which used to be a whitespace in earlier versions.
 The support for the `\{ansi}` option in exception converters is removed too.
 
+=== ANSI support on Windows
+
+Since 2017, Windows 10 and newer have offered native support for ANSI escapes.
+The support for the outdated Jansi 1.x library has therefore been removed.
+See xref:manual/pattern-layout.adoc#jansi[ANSI styling on Windows] for more 
information.
+
 <#include "../.changelog.adoc.ftl">
diff --git a/src/changelog/.2.x.x/1736_split_jansi_support.xml 
b/src/changelog/.2.x.x/1736_split_jansi_support.xml
new file mode 100644
index 0000000000..a585fed74f
--- /dev/null
+++ b/src/changelog/.2.x.x/1736_split_jansi_support.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="changed">
+  <issue id="1736" 
link="https://github.com/apache/logging-log4j2/issues/1736"/>
+  <description format="asciidoc">Remove JAnsi library support. Windows 10 
console has supported ANSI escapes since 2017.</description>
+</entry>
diff --git a/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml 
b/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml
new file mode 100644
index 0000000000..7fad82b6d5
--- /dev/null
+++ b/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="changed">
+  <issue id="2916" link="https://github.com/apache/logging-log4j2/pull/2916"/>
+  <description format="asciidoc">Rewrite `JAnsiTextRenderer` to work without 
JAnsi library.</description>
+</entry>
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index 8ec9a597b2..7cdcf41ecf 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -59,7 +59,6 @@ asciidoc:
     disruptor-version: "${site-disruptor.version}"
     flume-version: "${site-flume.version}"
     jackson-version: "${site-jackson.version}"
-    jansi-version: "${site-jansi.version}"
     javax-mail-version: "${site-javax-mail.version}"
     jctools-version: "${site-jctools.version}"
     je-version: "${site-je.version}"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index 21652d7e98..ff6edf566a 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -59,7 +59,6 @@ asciidoc:
     disruptor-version: "1.2.3-disruptor"
     flume-version: "1.2.3-flume"
     jackson-version: "1.2.3-jackson"
-    jansi-version: "1.2.3-jansi"
     javax-mail-version: "1.2.3-javax-mail"
     jctools-version: "1.2.3-jctools"
     je-version: "1.2.3-je"
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc 
b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index 6f0c4aaad7..a43675fb54 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@ -216,7 +216,7 @@ They are documented in separate pages based on their target 
resource:
 === Console Appender
 
 As one might expect, the Console Appender writes its output to either the 
standard output or standard error output.
-The appender supports four different ways to access the output streams:
+The appender supports three different ways to access the output streams:
 
 `direct`::
 This mode gives the best performance.
@@ -236,39 +236,6 @@ This setting might be useful in multi-application 
environments.
 Some application servers modify `System.out` and `System.err` to always point 
to the currently running application.
 ====
 
-`JANSI`::
-If the application is running on Windows and the
-https://fusesource.github.io/jansi/[JANSI library]
-is available, the Console appender will use JANSI to emulate ANSI sequence 
support.
-This mode can be disabled by setting the
-xref:manual/systemproperties.adoc#log4j2.skipJansi[`log4j2.skipJansi`]
-configuration attribute to `true`.
-+
-Additional runtime dependencies are required to use JANSI:
-+
-[tabs]
-====
-Maven::
-+
-[source,xml,subs="+attributes"]
-----
-<dependency>
-  <groupId>org.fusesource.jansi</groupId>
-  <artifactId>jansi</artifactId>
-  <version>{jansi-version}</version>
-</dependency>
-
-----
-
-Gradle::
-+
-[source,groovy,subs="+attributes"]
-----
-runtimeOnly 'org.fusesource.jansi:jansi:{jansi-version}'
-----
-
-====
-
 [#ConsoleAppender-attributes]
 .Console Appender configuration attributes
 [cols="1m,1,1,5"]
@@ -311,9 +278,7 @@ If other logging backends or the application itself uses 
`System.out/System.err`
 ====
 
 This setting is incompatible with the
-<<ConsoleAppender-attr-follow,`follow` attribute>>
-and
-xref:manual/systemproperties.adoc#log4j2.skipJansi[JANSI support].
+<<ConsoleAppender-attr-follow,`follow` attribute>>.
 
 | [[ConsoleAppender-attr-follow]]
 follow
@@ -328,9 +293,7 @@ 
https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#setOut-java.io.P
 Otherwise, the value of `System.out` (resp. `System.err`) at configuration 
time will be used.
 
 This setting is incompatible with the
-<<ConsoleAppender-attr-direct,`direct` attribute>>
-and
-xref:manual/systemproperties.adoc#log4j2.skipJansi[JANSI support].
+<<ConsoleAppender-attr-direct,`direct` attribute>>.
 
 | [[ConsoleAppender-attr-ignoreExceptions]]
 ignoreExceptions
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc 
b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index 1817b38822..4972398648 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -209,7 +209,7 @@ The optional footer to include at the bottom of each log 
file
 |Default value |`false`
 |===
 
-If `true`, do not output ANSI escape codes
+If `true`, do not output ANSI escape codes.
 
 [#plugin-attr-noConsoleNoAnsi]
 ==== `noConsoleNoAnsi`
@@ -220,7 +220,7 @@ If `true`, do not output ANSI escape codes
 |Default value |`false`
 |===
 
-If `true` and `System.console()` is null, do not output ANSI escape codes
+If `true` and `System.console()` is `null`, do not output ANSI escape codes
 
 [#plugin-elements]
 === Plugin elements
@@ -1598,19 +1598,14 @@ If your terminal supports 24-bit colors, you can 
specify:
 [#jansi]
 ==== ANSI styling on Windows
 
-ANSI escape sequences are supported natively on many platforms, but not by 
default on Windows.
-To enable ANSI support add the
-http://fusesource.github.io/jansi/[Jansi]
-dependency to your application, and set 
xref:manual/systemproperties.adoc#log4j2.skipJansi[the `log4j2.skipJansi` 
system property] to `false`.
-This allows Log4j to use Jansi to add ANSI escape codes when writing to the 
console.
+ANSI escape sequences are supported natively on many platforms, but are 
disabled by default in `cmd.exe` on Windows.
+To enable ANSI escape sequences, create a registry key named 
`HKEY_CURRENT_USER\Console\VirtualTerminalLevel` of type `DWORD` and set its 
value to `0x1`.
 
-[NOTE]
-====
-Before Log4j 2.10, Jansi was enabled by default.
-The fact that Jansi requires native code means that Jansi can only be loaded 
by a single class loader.
-For web applications, this means the Jansi jar has to be in the web 
container's classpath.
-To avoid causing problems for web applications, Log4j no longer automatically 
tries to load Jansi without explicit configuration from Log4j 2.10 onward.
-====
+See
+https://devblogs.microsoft.com/commandline/understanding-windows-console-host-settings/[Understanding
 Windows Console Host Settings]
+and
+https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences[Console
 Virtual Terminal Sequences]
+Microsoft documentation for more details.
 
 [#garbage-free]
 === Garbage-free configuration
diff --git a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc 
b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
index 2bd4b6e75e..318c745e10 100644
--- a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
@@ -149,13 +149,6 @@ 
include::partial$manual/systemproperties/properties-configuration-factory.adoc[l
 
 
include::partial$manual/systemproperties/properties-garbage-collection.adoc[leveloffset=+2]
 
-[id=properties-jansi]
-=== JANSI
-
-If the https://fusesource.github.io/jansi/[JANSI] library is on the runtime 
classpath of the application, the following property can be used to control its 
usage:
-
-include::partial$manual/systemproperties/properties-jansi.adoc[leveloffset=+2]
-
 [id=properties-jmx]
 === JMX
 
diff --git 
a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
 
b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
deleted file mode 100644
index 6b58ac8c58..0000000000
--- 
a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
+++ /dev/null
@@ -1,32 +0,0 @@
-////
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-////
-[id=log4j2.skipJansi]
-== `log4j2.skipJansi`
-
-[cols="1h,5"]
-|===
-| Env. variable | `LOG4J_SKIP_JANSI`
-| Type          | `boolean`
-| Default value | `true`
-|===
-
-If the following conditions are satisfied:
-
-* Log4j runs on Windows,
-* this property is set to `false`,
-
-Log4j will use the JANSI library to color the output of the console appender.
\ No newline at end of file


Reply via email to