Eclipse - Sonar S2629 可能误报新字符串
Eclipse - Sonar S2629 possible false positive with new String
我正在使用最新的 Eclipse 和 Sonar 插件
在 answer 中用于记录的是以下行:
log.debug("Request body: {}", new String(body, "UTF-8"));
只有在 DEBUG 级别才应该创建字符串:
/**
* 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
:
"Preconditions" and logging arguments should not require evaluation (squid:S2629)
并给出串联的例子
logger.log(Level.DEBUG, "Something went wrong: " + message); // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages
这是误报声纳警告还是我遗漏了什么?
这不是 的副本,后者通常询问规则概念,即连接,但不是通过创建对象格式化为 new String
另外 link 的一个答案说创建 new Date()
不会造成内置格式的问题:
public static void main(String[] args) {
LOGGER.info("The program started at {}", new Date());
}
}
Logging this way, you avoid performance overhead for strings concatenation when nothing should be actually logged.
在非调试模式下行
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,可以使用以下实用方法作为解决方法:
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)));
虽然使用 lambda 或惰性 lambda 很好,但仍然有很好的旧 isDebugEnabled
方式:
if (log.isDebugEnabled()) {
log.debug("Request body: {}", new String(body, StandardCharsets.UTF_8));
}
这不会修复正在创建的 String
(因为您毕竟想要显示它),但在禁用调试模式时不会消耗内存。
我正在使用最新的 Eclipse 和 Sonar 插件
在 answer 中用于记录的是以下行:
log.debug("Request body: {}", new String(body, "UTF-8"));
只有在 DEBUG 级别才应该创建字符串:
/**
* 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
:
"Preconditions" and logging arguments should not require evaluation (squid:S2629)
并给出串联的例子
logger.log(Level.DEBUG, "Something went wrong: " + message); // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages
这是误报声纳警告还是我遗漏了什么?
这不是 new String
另外 link 的一个答案说创建 new Date()
不会造成内置格式的问题:
public static void main(String[] args) { LOGGER.info("The program started at {}", new Date()); } }
Logging this way, you avoid performance overhead for strings concatenation when nothing should be actually logged.
在非调试模式下行
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,可以使用以下实用方法作为解决方法:
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)));
虽然使用 lambda 或惰性 lambda 很好,但仍然有很好的旧 isDebugEnabled
方式:
if (log.isDebugEnabled()) {
log.debug("Request body: {}", new String(body, StandardCharsets.UTF_8));
}
这不会修复正在创建的 String
(因为您毕竟想要显示它),但在禁用调试模式时不会消耗内存。