【问题标题】:Sonar maven plugin hangs during Java Main Files AST scan在 Java 主文件 AST 扫描期间,Sonar maven 插件挂起
【发布时间】:2019-08-22 19:11:15
【问题描述】:

我正在使用 sonar maven 插件来触发 java 代码分析。

Sonar-runner 卡在一个 java 文件处理上。控制台上的最后一条消息读取 Java AST Scan 并且进程卡在了那里..

SonarQube 版本:7.3.0

Sonar-maven-plugin 版本:3.6.0.1398(最新版本),但也尝试使用 3.4.1.1168

日志如下所示:

[INFO] Java Main Files AST scan
[INFO] 12/41 files analyzed, current file: {path-to-file}/Foo.java
[INFO] 12/41 files analyzed, current file: {path-to-file}/Foo.java
[INFO] 12/41 files analyzed, current file: {path-to-file}/Foo.java
[INFO] 12/41 files analyzed, current file: {path-to-file}/Foo.java
...

OOM 异常堆栈跟踪:

12:30:17 [SonarQube analysis] [ERROR] Java heap space -> [Help 1]
12:30:17 [SonarQube analysis] java.lang.OutOfMemoryError: Java heap space
12:30:17 [SonarQube analysis]     at org.sonar.java.collections.AVLTree$Equals.compute (AVLTree.java:455)
12:30:17 [SonarQube analysis]     at org.sonar.java.collections.AVLTree$Node.equals (AVLTree.java:387)
12:30:17 [SonarQube analysis]     at java.util.Objects.equals (Objects.java:77)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ProgramState.equals (ProgramState.java:260)
12:30:17 [SonarQube analysis]     at java.util.Objects.equals (Objects.java:77)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraph$Node.equals (ExplodedGraph.java:124)
12:30:17 [SonarQube analysis]     at java.util.HashMap$TreeNode.find (HashMap.java:1919)
12:30:17 [SonarQube analysis]     at java.util.HashMap$TreeNode.find (HashMap.java:1929)
12:30:17 [SonarQube analysis]     at java.util.HashMap$TreeNode.putTreeVal (HashMap.java:2048)
12:30:17 [SonarQube analysis]     at java.util.HashMap.putVal (HashMap.java:638)
12:30:17 [SonarQube analysis]     at java.util.HashMap.put (HashMap.java:612)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraph.node (ExplodedGraph.java:55)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraphWalker.enqueue (ExplodedGraphWalker.java:1101)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraphWalker.enqueue (ExplodedGraphWalker.java:1083)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraphWalker.enqueue (ExplodedGraphWalker.java:1075)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraphWalker.execute (ExplodedGraphWalker.java:231)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.ExplodedGraphWalker.visitMethod (ExplodedGraphWalker.java:209)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.SymbolicExecutionVisitor.execute (SymbolicExecutionVisitor.java:74)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.SymbolicExecutionVisitor.visitNode (SymbolicExecutionVisitor.java:64)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.visit (SubscriptionVisitor.java:103)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren (SubscriptionVisitor.java:128)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.visit (SubscriptionVisitor.java:105)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren (SubscriptionVisitor.java:128)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.visit (SubscriptionVisitor.java:105)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.scanTree (SubscriptionVisitor.java:86)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.visitors.SubscriptionVisitor.scanFile (SubscriptionVisitor.java:72)
12:30:17 [SonarQube analysis]     at org.sonar.java.se.SymbolicExecutionVisitor.scanFile (SymbolicExecutionVisitor.java:54)
12:30:17 [SonarQube analysis]     at org.sonar.java.model.VisitorsBridge.runScanner (VisitorsBridge.java:148)
12:30:17 [SonarQube analysis]     at org.sonar.java.model.VisitorsBridge.visitFile (VisitorsBridge.java:136)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.JavaAstScanner.simpleScan (JavaAstScanner.java:96)
12:30:17 [SonarQube analysis]     at org.sonar.java.ast.JavaAstScanner.scan (JavaAstScanner.java:68)
12:30:17 [SonarQube analysis]     at org.sonar.java.JavaSquid.scanSources (JavaSquid.java:113)

几个小时后它只是抛出 Out Of Memory 异常

顺便说一下,这个Foo.java 代表带有谷歌自动价值生成的pojo -> com.google.auto.value.AutoValue

有人对此有什么想法吗?

【问题讨论】:

    标签: java maven sonarqube sonarqube-scan


    【解决方案1】:

    SonarQube 的 SonarJava 插件包含一些依赖于 符号执行 (SE) 引擎的规则,在分析期间执行(特别是如果您使用 SonarWay 质量配置文件) .从您的日志来看,这就是 OOME 的根源。

    此引擎允许某些 SonarJava 错误检测规则发现问题,具体取决于方法内可能的执行路径(在某些情况下,还可以跟踪对其他方法的方法调用)。

    这个引擎非常消耗资源。它生成可能的程序状态图(称为爆炸图),根据某些约束模拟所有方法执行路径。图表的大小取决于很多因素。方法体的复杂性是一个(条件、循环等的数量),另一个是参数的数量,因为它代表了分析的尽可能多的起点。

    理论上,每个文件都会重新启动一个新的分解图,并释放内存。虽然依赖 SE 引擎的所有规则都共享同一个图来识别给定文件上的问题,但如果图变得过大,仍然会发生内存爆炸。

    所以你有几个选择:

    • 尝试增加允许进行分析的内存。希望它能让 SE 引擎覆盖所有状态并结束执行。
    • 从可能具有大量参数的构造函数或方法的分析文件中排除(从 15-20 开始,我确实预计引擎会开始遭受很多损失)。通常,建议避免分析生成的代码。
    • 最终,禁用所有使用 SE 引擎的规则。您将在此文件夹中找到规则密钥:SonarSource/sonar-java/.../se/checks(查看 @Rule() 注释以获取规则密钥)

    理想情况下,如果您可以系统地隔离重现问题的源代码,并提取自包含代码 sn-p(仅使用本机 java 类进行编译,没有外部依赖项),这将有助于识别潜在的内存引擎中的泄漏,或定义一些启发式方法以避免在引擎无论如何都无法完成的方法/构造函数上浪费时间。

    【讨论】:

    • 迈克尔,感谢您的周到解释。是的,在分析该工厂方法的所有可能变体/路径时看起来像声纳,捕获了不定式调用循环。顺便说一句,我分析了非生成代码,因为自动值表示抽象类 pojo,并且在编译阶段它在生成的包中创建了完全成熟的 pojo从扫描中排除。
    【解决方案2】:

    承认这很有趣,但是当我删除带有 35 个参数的工厂方法(是的,它是大 pojo)时,它开始成功通过分析。所以它可能是特定于代码的问题。

    【讨论】:

      猜你喜欢
      • 2017-08-09
      • 1970-01-01
      • 2018-05-31
      • 2017-12-16
      • 2016-11-30
      • 1970-01-01
      • 2015-05-08
      • 2013-10-04
      • 1970-01-01
      相关资源
      最近更新 更多