Eclipse - Sonar S2629 可能使用新字符串出现误报
Posted
技术标签:
【中文标题】Eclipse - Sonar S2629 可能使用新字符串出现误报【英文标题】:Eclipse - Sonar S2629 possible false positive with new String 【发布时间】: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());
以这种方式记录,可以避免在实际不记录任何内容时字符串连接的性能开销。
【问题讨论】:
【参考方案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
(因为您毕竟想显示它),但在禁用调试模式时不会消耗内存。
【讨论】:
以上是关于Eclipse - Sonar S2629 可能使用新字符串出现误报的主要内容,如果未能解决你的问题,请参考以下文章
Sonar6.0应用之三:集成Eclipse实时代码质量分析(附Eclipse初始化)
使 Sonar Runner Gradle 任务依赖于我的一项任务