Log4j2在方法引用调用中打印实用程序类行号

时间:2018-01-18 20:04:02

标签: java lambda log4j2

我有一段代码如下,

List<String> someList = new ArrayList<>();
someList.add("abc1");
someList.add("abc2");
someList.add("abc3");
someList.add("abc4");
someList.add("abc5");

someList.forEach(logger::debug);
someList.forEach(l -> logger.debug(l));

在方法参考样式中,输出如下 -

[com.some.pkg.AppContext:1249] abc1
[com.some.pkg.AppContext:1249] abc2
[com.some.pkg.AppContext:1249] abc3
[com.some.pkg.AppContext:1249] abc4
[com.some.pkg.AppContext:1249] abc5

虽然,对于lambda,输出是预期的。

[com.some.pkg.AppContext:36] abc1
[com.some.pkg.AppContext:36] abc2
[com.some.pkg.AppContext:36] abc3
[com.some.pkg.AppContext:36] abc4
[com.some.pkg.AppContext:36] abc5

模式为[%logger{36}:%L]

此外,如果我使用%F,则方法引用会打印ArrayList.java,但lambda会打印预期的类。

我不确定我是否遗漏了某些内容,或者这是log4j2的错误/限制。

1 个答案:

答案 0 :(得分:1)

我认为从log4j2开始,这是预期的行为。由于在java中执行方法引用和lambda表达式的方式不同,因此存在差异。

根据log4j2 documentation -

  

如果其中一个布局配置了与位置相关的属性   像HTML locationInfo,或其中一个模式%C或%class,%F或   %file,%l或%location,%L或%line,%M或%方法,Log4j将采用   堆栈的快照,并遍历堆栈跟踪以查找位置   信息。

简单来说,log4j使用stack trace来确定日志语句的位置信息。

当调用info()类的debug()AbstraceLogger等任何方法时,它会查找当前stack trace以确定调用方的位置。

如果是方法参考,stack trace如下所示 -

Method Reference Stack trace

注意顶部的第3行 - ArrayList,第1380行。我认为第2行被忽略,因为它没有给出文件名和行号的有效值。

如果是lambda表达式,stack trace看起来像 -

Lambda Expressions Stack trace

正如您所看到的,两种情况下debug()方法的最后一个调用方是不同的,因此是行号。

使用您给定的代码,我也收到以下日志 -

com.some.pkg.AppContext:1380
com.some.pkg.AppContext:1380
com.some.pkg.AppContext:1380
com.some.pkg.AppContext:1380
com.some.pkg.AppContext:1380
com.some.pkg.AppContext:36
com.some.pkg.AppContext:36
com.some.pkg.AppContext:36
com.some.pkg.AppContext:36
com.some.pkg.AppContext:36

输出与%F模式的差异也与此解释有关。使用%F模式,stack trace用于查找文件名。 Logger不需要stack trace查询。