【问题标题】:How does Log4j 2.x implement lazy argument evaluation?Log4j 2.x 如何实现惰性参数评估?
【发布时间】:2015-08-24 13:47:45
【问题描述】:

鉴于Java argument evaluation mechanism,Log4j 2.x在使用大括号格式化消息时如何实现lazy evaluation,以“避免参数构造成本”禁用日志?

例如

logger.debug("Entry number: {} is {}", i, entry[i]);

【问题讨论】:

    标签: java log4j2 lazy-evaluation


    【解决方案1】:

    我猜 Log4j 的意思是,用大括号,它们避免在不需要时构造字符串(例如,Level 不是 Debug):

    有

    logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    

    即使没有记录,也始终会计算完整的消息。

    有

    logger.debug("Entry number: {} is {}", i, entry[i]);
    

    Log4j 可以先检查 Log-Level,然后决定是否值得构造消息字符串。这节省了字符串连接所需的资源。如果消息实际正在创建,它只会在提供的对象上调用toString(),从而节省更多的计算成本。

    Log4j 使用一个内部类 (org.apache.logging.log4j.message.ParameterFormatter) 将每个 {} 替换为提供的参数。它还会捕获toString() 抛出的异常并报告这些故障。

    【讨论】:

    • 清除。所以它只是推迟了字符串构造而不是参数评估。
    • 这个答案是关于 slf4j 的,不适用于有问题的 vanilla log4j(至少适用于 log4j 1.x)。虽然可以使用 slf4j API 代理到 log4j 实现,但应该更清楚地说明它们之间的区别。 slf4j 类绝不是 log4j 的“内部”。更多正确答案请查看Log4j Implicit String Formatting。
    • @Vadzim 感谢您的提示,那时我的类路径中一定有 SLF4j 并且走错了兔子洞。作为问题中的示例和 log4j2 的链接,问题是关于 log4j2,而不是 log4j 1.x。我更新了问题,使其更清晰。
    【解决方案2】:

    为避免参数评估,只需将其包装在 lambda 中:

    logger.debug(() -> { 
       "Entry number: " + i + " is " + String.valueOf(entry[i])
    });
    

    在这种形式中,只有在实际伐木之前,才会要求供应商进行施工。把它想象成一个函数声明。

    【讨论】:

    • 这值得一票,因为它也是一个有效的选项,尽管接受的答案更接近于回答所提出的问题。
    猜你喜欢
    • 2019-01-12
    • 2014-02-08
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2013-03-11
    • 2017-01-18
    • 2018-11-11
    相关资源
    最近更新 更多