SonarQube java:S2189无限循环误报问题咨询
问题现象
Java代码静态检测过程中,SonarQube规则java:S2189抛出Bug级提示,提示内容为Loops should not be infinite(循环不应为无限循环)。对应循环逻辑已设置明确终止条件,常规排查未定位到问题触发根源。
经版本对比验证,该提示触发与否和SonarQube Scanner版本直接相关,不同版本检测结果存在明确差异:
- SonarQube Scanner 4.2.0.1873版本检测时会稳定触发该Bug提示
- SonarQube Scanner 3.0.3.778版本检测同一段代码无任何相关提示
触发问题的复现代码如下:
public class SonarBug implements Runnable { private final LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(); @Override public void run() { boolean continueCondition = true; while (continueCondition) { Integer takenInteger; try { takenInteger = queue.take(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); continueCondition = false; continue; } callSomeFunction(takenInteger); } System.out.println("Finished."); } private void callSomeFunction(Integer takenInteger) { } }
根本原因
这是SonarQube Scanner 4.2.0版本控制流分析模块的逻辑缺陷导致的规则误报,代码本身的循环逻辑不存在无限循环问题。
该版本的流分析引擎在处理这段代码时存在两处判定偏差:
- 对
LinkedBlockingQueue.take()这类声明抛出受检异常的阻塞方法做路径建模时,错误判定方法调用后不存在正常返回、向下执行的可达路径,忽略了方法成功从队列获取元素后正常返回的常规场景 - 追踪局部布尔类型循环控制变量的赋值传递时,没有覆盖catch块内通过
continue跳转回循环头的执行路径,未识别到catch分支中continueCondition = false的赋值会作用于下一次循环的条件判断
两个偏差叠加后,规则引擎错误判定该while循环不存在任何可到达的退出路径,因此触发了无限循环的规则告警。3.0.3版本的控制流分析粒度较粗,既不会对阻塞方法的执行路径做特殊建模,也不会跨异常分支做细粒度的变量状态追踪,因此不会触发该误报。
规避方案
如果需要在保留4.x版本Scanner的前提下消除该误报,不要通过局部布尔变量+continue的方式控制循环终止,改为显式通过break标记循环退出点即可,所有版本的分析引擎都能正确识别这类明确的退出路径,调整后的参考代码如下:
public class SonarBug implements Runnable { private final LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(); @Override public void run() { while (true) { Integer takenInteger; try { takenInteger = queue.take(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } callSomeFunction(takenInteger); } System.out.println("Finished."); } private void callSomeFunction(Integer takenInteger) { } }
也可以直接用线程中断状态作为循环判断条件,同样可以避免该误报。
内容的提问来源于stack exchange,提问作者Onur Öçalan
相关产品推荐
相关产品推荐

