最新 (2.14.1) Log4J2 async appender 导致 Java 进程挂起
Latest (2.14.1) Log4J2 async appender causes Java process to hang
我有一个非常基础(几乎是教科书)的 Log4J2 示例,使用最新版本 (2.14.1):
log4j2.xml
(取自official appender doc):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="Async">
<AppenderRef ref="MyFile"/>
</Async>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>
计划,TestLog.java
:
public class TestLog {
private static final org.apache.logging.log4j.Logger l = org.apache.logging.log4j.LogManager.getLogger(TestLog.class);
public static void main(String[] args) {
l.error("Boo");
}
}
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tuna</groupId>
<artifactId>log4j2-not-shutting-down</artifactId>
<version>0</version>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
当我 运行 这样做时,我确实在 logs/app.log
中得到了预期的错误日志行;但是 Java 进程挂起(在 main()
完成后不会关闭)。线程转储显示(除了 Java 的本机线程之外)一个非守护进程异步附加线程仍然 WAITING
(很可能是挂起的原因)。
"Log4j2-AsyncAppenderEventDispatcher-1-Async" #15 prio=5 os_prio=0 cpu=0.00ms elapsed=17.04s tid=0x000001bd5bc98000 nid=0x7324 waiting on condition [0x0000006962bff000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park(java.base@12/Native Method)
- parking to wait for <0x00000007110c2618> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081)
at java.util.concurrent.ArrayBlockingQueue.take(java.base@12/ArrayBlockingQueue.java:417)
at org.apache.logging.log4j.core.appender.AsyncAppenderEventDispatcher.dispatchAll(AsyncAppenderEventDispatcher.java:70)
at org.apache.logging.log4j.core.appender.AsyncAppenderEventDispatcher.run(AsyncAppenderEventDispatcher.java:62)
- 删除
Async
appender(并直接附加到 MyFile
)会导致程序正常关闭。
- 向
Async
appender 定义添加 shutdownTimeout
无效。 (无论如何,唯一的日志行已经正确写入文件,所以它不可能是排队问题。)
- 将
log4j-core
切换到较低版本(例如 2.9.1
)也可以解决挂起问题。
这是预期的行为还是错误?我错过了什么吗?
似乎是 already reported and fixed。
无论如何 2.14.1 不再可行(由于臭名昭著 CVE-2021-44228 RCE vulnerability), and given the several vulnerabilities discovered afterwards 现在建议升级到 2.17.0 或更高版本 - 最初声明的 LOG4J2-3102 也已修复。
我有一个非常基础(几乎是教科书)的 Log4J2 示例,使用最新版本 (2.14.1):
log4j2.xml
(取自official appender doc):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="Async">
<AppenderRef ref="MyFile"/>
</Async>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>
计划,TestLog.java
:
public class TestLog {
private static final org.apache.logging.log4j.Logger l = org.apache.logging.log4j.LogManager.getLogger(TestLog.class);
public static void main(String[] args) {
l.error("Boo");
}
}
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tuna</groupId>
<artifactId>log4j2-not-shutting-down</artifactId>
<version>0</version>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
当我 运行 这样做时,我确实在 logs/app.log
中得到了预期的错误日志行;但是 Java 进程挂起(在 main()
完成后不会关闭)。线程转储显示(除了 Java 的本机线程之外)一个非守护进程异步附加线程仍然 WAITING
(很可能是挂起的原因)。
"Log4j2-AsyncAppenderEventDispatcher-1-Async" #15 prio=5 os_prio=0 cpu=0.00ms elapsed=17.04s tid=0x000001bd5bc98000 nid=0x7324 waiting on condition [0x0000006962bff000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park(java.base@12/Native Method)
- parking to wait for <0x00000007110c2618> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081)
at java.util.concurrent.ArrayBlockingQueue.take(java.base@12/ArrayBlockingQueue.java:417)
at org.apache.logging.log4j.core.appender.AsyncAppenderEventDispatcher.dispatchAll(AsyncAppenderEventDispatcher.java:70)
at org.apache.logging.log4j.core.appender.AsyncAppenderEventDispatcher.run(AsyncAppenderEventDispatcher.java:62)
- 删除
Async
appender(并直接附加到MyFile
)会导致程序正常关闭。 - 向
Async
appender 定义添加shutdownTimeout
无效。 (无论如何,唯一的日志行已经正确写入文件,所以它不可能是排队问题。) - 将
log4j-core
切换到较低版本(例如2.9.1
)也可以解决挂起问题。
这是预期的行为还是错误?我错过了什么吗?
似乎是 already reported and fixed。
无论如何 2.14.1 不再可行(由于臭名昭著 CVE-2021-44228 RCE vulnerability), and given the several vulnerabilities discovered afterwards 现在建议升级到 2.17.0 或更高版本 - 最初声明的 LOG4J2-3102 也已修复。