【问题标题】:Eclipse - Sonar S2629 possible false positive with new StringEclipse - Sonar S2629 可能使用新字符串出现误报
【发布时间】:2019-04-01 13:53:48
【问题描述】:

我正在使用最新的 Eclipse 和 Sonar 插件

answer 用于记录有以下行:

log.debug("Request body: {}", new String(body, "UTF-8"));

只有在调试级别才应该创建字符串:

/**
 * Log a message at the DEBUG level according to the specified format
 * and argument.
 * <p/>
 * <p>This form avoids superfluous object creation when the logger
 * is disabled for the DEBUG level. </p>
 *
 * @param format the format string
 * @param arg    the argument
 */
public void debug(String format, Object arg);

但 Sonar 将其标记为 squid:S2629

“先决条件”和日志记录参数不应需要评估 (squid:S2629)

并给出连接示例

logger.log(Level.DEBUG, "出了点问题:" + message); // 不合规的;即使日志级别太高而无法显示 DEBUG 消息,也会执行字符串连接

这是误报声纳警告还是我遗漏了什么?

这不是 this question 的重复,它通常询问规则概念,即连接,但不是将创建对象格式化为 new String

另外link 的答案说创建new Date() 不会产生内置格式的问题:

public static void main(String[] args) {
    LOGGER.info("The program started at {}", new Date());
}

}

以这种方式记录,可以避免在实际不记录任何内容时字符串连接的性能开销。

【问题讨论】:

    标签: java eclipse sonarqube sonarlint-eclipse


    【解决方案1】:

    在非调试模式下该行

    log.debug("Request body: {}", new String(body, "UTF-8"));
    

    而不是

    log.debug(MessageFormatter.format("Request body: {}", new String(body, "UTF-8")));
    

    避免创建通过MessageFormatter.format(String messagePattern, Object arg) 创建的字符串,但不创建由new String(body, "UTF-8") 创建的其他字符串。

    这意味着它不是误报,因为在调用记录方法之前首先计算参数。

    只要SLF4J does not support lambda expression to lazy evaluate arguments(见comment by ZhekaKozlov),可以使用以下实用方法作为解决方法:

    private static Object lazyToString(final Supplier<String> stringSupplier) {
        return new Object() {
            @Override
            public String toString() {
                return stringSupplier.get();
            }
        };
    }
    

    这可用于将字节数组转换为字符串仅限于 DEBUG 模式:

    log.debug("Request body: {}", lazyToString(() -> new String(body, StandardCharsets.UTF_8)));
    

    【讨论】:

      【解决方案2】:

      虽然使用 lambda 或惰性 lambda 没问题,但仍然有很好的旧 isDebugEnabled 方式:

      if (log.isDebugEnabled()) {
        log.debug("Request body: {}", new String(body, StandardCharsets.UTF_8));
      }
      

      这不会修复正在创建的String(因为您毕竟想显示它),但在禁用调试模式时不会消耗内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-14
        • 2020-11-27
        • 1970-01-01
        相关资源
        最近更新 更多