env:
弹簧靴1.5.9.RELEASE
spring-boot-starter-log4j2(是Log4j 2.7版本)
所有输出信息的大小为9KB,包括所有spring boot输出
这是我的log4j2.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="pid">???</Property>
<Property name="logPattern">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:pid}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
<Property name="fileLogPattern">%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n\n</Property>
<Property name="logPath">/data/server/tomcat/logs/bbPurchaseAgency</Property>
<!-- for SizeBasedTriggeringPolicy, this is the problem, but I need file split function -->
<Property name="fileSplitSize">2KB</Property>
<Property name="fileSplitTime">1</Property>
<Property name="maxSurviveTime">30d</Property>
</Properties>
<Appenders>
<Console name="developLog" target="SYSTEM_OUT" follow="true">
<PatternLayout charset="${encoding}" pattern="${logPattern}"/>
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny"/>
</Console>
<RollingFile name="infoFile" fileName="${logPath}/bbPurchaseAgency_info.log"
filePattern="${logPath}/bbPurchaseAgency_info_%d{yyyy-MM-dd}-%i.log">
<PatternLayout charset="${encoding}" pattern="${fileLogPattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${fileSplitTime}"/>
<SizeBasedTriggeringPolicy size="${fileSplitSize}"/>
</Policies>
<Filters>
<!-- this filter will be print all information whatever level it is -->
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny"/>
<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="warn" onMatch="deny" onMismatch="neutral"/>
</Filters>
<DefaultRolloverStrategy>
<Delete basePath="${logPath}" maxDepth="1">
<IfFileName glob="bbPurchaseAgency_info_%d{yyyy-MM-dd}-%i.log" />
<IfLastModified age="${maxSurviveTime}"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="warnFile" fileName="${logPath}/bbPurchaseAgency_warn.log"
filePattern="${logPath}/bbPurchaseAgency_warn_%d{yyyy-MM-dd}-%i.log">
<PatternLayout charset="${encoding}" pattern="${fileLogPattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${fileSplitTime}"/>
<SizeBasedTriggeringPolicy size="${fileSplitSize}"/>
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral"/>
<ThresholdFilter level="warn" onMatch="accept" onMismatch="deny"/>
</Filters>
<DefaultRolloverStrategy>
<Delete basePath="${logPath}" maxDepth="1">
<IfFileName glob="bbPurchaseAgency_warn_%d{yyyy-MM-dd}-%i.log" />
<IfLastModified age="${maxSurviveTime}"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="errorFile" fileName="${logPath}/bbPurchaseAgency_error.log"
filePattern="${logPath}/bbPurchaseAgency_error_%d{yyyy-MM-dd}-%i.log">
<PatternLayout charset="${encoding}" pattern="${fileLogPattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="${fileSplitTime}"/>
<SizeBasedTriggeringPolicy size="${fileSplitSize}"/>
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="accept" onMismatch="deny"/>
</Filters>
<DefaultRolloverStrategy>
<Delete basePath="${logPath}" maxDepth="1">
<IfFileName glob="bbPurchaseAgency_error_%d{yyyy-MM-dd}-%i.log" />
<IfLastModified age="${maxSurviveTime}"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<AsyncLogger name="com.baibu.purchaseAgency" level="info" includeLocation="false">
<AppenderRef ref="infoFile"/>
</AsyncLogger>
<AsyncLogger name="com.baibu.purchaseAgency" level="warn" includeLocation="true">
<AppenderRef ref="warnFile"/>
</AsyncLogger>
<AsyncLogger name="com.baibu.purchaseAgency" level="error" includeLocation="true">
<AppenderRef ref="errorFile"/>
</AsyncLogger>
<Root level="info">
<AppenderRef ref="developLog"/>
<AppenderRef ref="infoFile"/>
<AppenderRef ref="warnFile"/>
<AppenderRef ref="errorFile"/>
</Root>
</Loggers>
</Configuration>
所以,这是一个问题:
当我主动启动spring boot并通过引发异常进行测试时,log4j2打印一些内容,并触发我设计的异常,然后spring log boot无法停止,因为log4j2内存泄漏。
这是测试代码:
@Value( "${spring.datasource.url}" )
public void checkDataSource( String url ) {
logger.warn( "warning url" );
logger.error( "error url" );
Integer.parseInt( url ); // I raise an exception when spring boot starting
}
这是堆栈信息:
The web application [ROOT] appears to have started a thread named [Log4j2-TF-4-1a752144-3] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:745)
然后运行其他测试,例如关闭文件拆分功能(将fileSplitSize设置为512MB),或者执行以下操作:
@Value( "${spring.datasource.url}" )
public void checkDataSource( String url ) {
new Thread( new Runnable() {
@Override
public void run() {
try {
Thread.sleep( 10 * 1000 );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.exit( 0 );
}
} ).start();
}
什么也没有发生,一切都很好,没有内存泄漏。...
我还在log4j2网站(http://logging.apache.org/log4j/2.x/manual/webapp.html)上看到以下描述:
为避免出现问题,当包含log4j-web jar时,将自动禁用Log4j关闭挂钩。
我做到了,但是没有用。
Log4j2的gitHub没有问题板,并且在网络上关于log4j2内存泄漏的信息很少,有人可以给我一些解决方案吗?非常感谢!