SonarJava 4.5, ClassCastException: BinaryExpressionTreeImpl cannot be cast to MethodInvocationTree

288 views
Skip to first unread message

ola.p...@mobenga.com

unread,
Feb 27, 2017, 6:55:40 AM2/27/17
to SonarQube
Hi.

Using SonarQube 5.6.6. 
After upgrading the SonarJava plugin from the pre-installed version 3.13.1 to version 4.5, It is no longer possible to analyze the code.
Instead it will result in a ClassCastException.

I have created a simple project to re-create the issue. Be aware that the code does not make any sense in itself.

package test;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;

public class SonarFail {

   
private ConcurrentMap<String, ReentrantLock> locks = new ConcurrentHashMap<>();

   
public ReentrantLock getLock(String id) {
       
ReentrantLock lock = locks.computeIfAbsent(id, s -> new ReentrantLock());
       
lock.lock();
       
try {
           
if (locks.get(id) == lock) {
               
return lock;
           
}
           
return null;
       
} finally {
           
lock.unlock();
       
}
   
}

}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
<modelVersion>4.0.0</modelVersion>

   
<groupId>test</groupId>
   
<artifactId>test</artifactId>
   
<version>1.0-SNAPSHOT</version>

   
<build>
       
<plugins>
           
<plugin>
               
<groupId>org.apache.maven.plugins</groupId>
               
<artifactId>maven-compiler-plugin</artifactId>
               
<configuration>
                   
<source>1.8</source>
                   
<target>1.8</target>
               
</configuration>
           
</plugin>
       
</plugins>
   
</build>

</project>

Running "mvn clean install sonar:sonar " on this source will fail with the following exception.

[ERROR] Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar (default-cli) on project test: SonarQube is unable to analyze file : '/test/src/main/java/test/SonarFail.java': org.sonar.java.model.expression.BinaryExpressionTreeImpl cannot be cast to org.sonar.plugins.java.api.tree.MethodInvocationTree -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar (default-cli) on project test: SonarQube is unable to analyze file : '/test/src/main/java/test/SonarFail.java'
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: SonarQube is unable to analyze file : '/test/src/main/java/test/SonarFail.java'
        at org.sonarsource.scanner.maven.bootstrap.ExceptionHandling.handle(ExceptionHandling.java:36)
        at org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.execute(ScannerBootstrapper.java:81)
        at org.sonarsource.scanner.maven.SonarQubeMojo.execute(SonarQubeMojo.java:122)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
        ... 20 more
Caused by: org.sonar.squidbridge.api.AnalysisException: SonarQube is unable to analyze file : '/test/src/main/java/test/SonarFail.java'
        at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:93)
        at org.sonar.java.ast.JavaAstScanner.scan(JavaAstScanner.java:67)
        at org.sonar.java.JavaSquid.scanSources(JavaSquid.java:114)
        at org.sonar.java.JavaSquid.scan(JavaSquid.java:108)
        at org.sonar.plugins.java.JavaSquidSensor.execute(JavaSquidSensor.java:87)
        at org.sonar.batch.sensor.SensorWrapper.analyse(SensorWrapper.java:57)
        at org.sonar.batch.phases.SensorsExecutor.executeSensor(SensorsExecutor.java:58)
        at org.sonar.batch.phases.SensorsExecutor.execute(SensorsExecutor.java:50)
        at org.sonar.batch.phases.AbstractPhaseExecutor.execute(AbstractPhaseExecutor.java:83)
        at org.sonar.batch.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:192)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
        at org.sonar.batch.scan.ProjectScanContainer.scan(ProjectScanContainer.java:241)
        at org.sonar.batch.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:236)
        at org.sonar.batch.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:226)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
        at org.sonar.batch.task.ScanTask.execute(ScanTask.java:47)
        at org.sonar.batch.task.TaskContainer.doAfterStart(TaskContainer.java:86)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
        at org.sonar.batch.bootstrap.GlobalContainer.executeTask(GlobalContainer.java:106)
        at org.sonar.batch.bootstrapper.Batch.executeTask(Batch.java:119)
        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:62)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
        at com.sun.proxy.$Proxy23.execute(Unknown Source)
        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:233)
        at org.sonarsource.scanner.api.EmbeddedScanner.runAnalysis(EmbeddedScanner.java:151)
        at org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.execute(ScannerBootstrapper.java:78)
        ... 23 more
Caused by: java.lang.ClassCastException: org.sonar.java.model.expression.BinaryExpressionTreeImpl cannot be cast to org.sonar.plugins.java.api.tree.MethodInvocationTree
        at org.sonar.java.se.checks.LocksNotUnlockedCheck.reportIssue(LocksNotUnlockedCheck.java:181)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
        at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
        at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
        at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1548)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
        at org.sonar.java.se.checks.LocksNotUnlockedCheck.checkEndOfExecutionPath(LocksNotUnlockedCheck.java:177)
        at org.sonar.java.se.CheckerDispatcher.executeCheckEndOfExecutionPath(CheckerDispatcher.java:131)
        at org.sonar.java.se.ExplodedGraphWalker.lambda$handleEndOfExecutionPath$0(ExplodedGraphWalker.java:287)
        at java.lang.Iterable.forEach(Iterable.java:75)
        at org.sonar.java.se.ExplodedGraphWalker.handleEndOfExecutionPath(ExplodedGraphWalker.java:284)
        at org.sonar.java.se.ExplodedGraphWalker.execute(ExplodedGraphWalker.java:248)
        at org.sonar.java.se.ExplodedGraphWalker.visitMethod(ExplodedGraphWalker.java:193)
        at org.sonar.java.se.ExplodedGraphWalker.visitMethod(ExplodedGraphWalker.java:186)
        at org.sonar.java.se.SymbolicExecutionVisitor.execute(SymbolicExecutionVisitor.java:78)
        at org.sonar.java.se.SymbolicExecutionVisitor.visitNode(SymbolicExecutionVisitor.java:63)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:95)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren(SubscriptionVisitor.java:120)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:97)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren(SubscriptionVisitor.java:120)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:97)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.scanTree(SubscriptionVisitor.java:78)
        at org.sonar.java.ast.visitors.SubscriptionVisitor.scanFile(SubscriptionVisitor.java:64)
        at org.sonar.java.model.VisitorsBridge.visitFile(VisitorsBridge.java:118)
        at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:84)
        ... 55 more


SonarJava 4.6-RC1 gives the same exception.

Regards 
Ola Persson

Nicolas Peru

unread,
Feb 27, 2017, 8:54:12 AM2/27/17
to ola.p...@mobenga.com, SonarQube
Hi, 

Thanks for the reproducer and the feedback. And special thanks for testing 4.6-RC1 !

The class cast exception is only the tip of the iceberg  : Se engine is assuming that for this lock check only method invocation tree will be reported as sources of locking checks. But in your example, we learn from the if, that the value returned by the get call is actually locked -> hence the assumption is wrong and we end up with the exception. 
But that means that we were trying to report that the value returned from the get call on the map was actually left locked. This is wrong and this comes from the modelization of == operator and when we learn that it's true or false. What's happening under the hood is that when the right operand of that relation is unlocked, we don't learn the same thing on the left operand.

This last part is not an easy problem (at all) and as such won't be addressed fast. However, we definitely don't want to fail the analysis and raise false positives : so let's eliminate the noise for 4.6 and see how we can fix that properly afterwards : https://jira.sonarsource.com/browse/SONARJAVA-2140  

Thanks again, your bug report will help us to improve the next version ! 

Cheers, 


This communication (including any attachments) is sent on behalf of Playtech plc or one of its subsidiaries (Playtech Group). It contains information which is confidential and privileged. If you are not the intended recipient, please notify the sender immediately and destroy any copies of this communication. Unless expressly stated to the contrary, nothing in this communication constitutes a contractual offer capable of acceptance or indicates intention to create legal relations or grant any rights. The Playtech Group monitors communications sent or received by it for security and other purposes. Any views or opinions presented are solely those of the author and do not necessarily represent those of the Playtech Group

--
You received this message because you are subscribed to the Google Groups "SonarQube" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sonarqube+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sonarqube/3a3f7ef9-e0bc-43ee-b76e-e16ef4719b61%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Nicolas PERU | SonarSource
Senior Developer
http://sonarsource.com

ola.p...@mobenga.com

unread,
Feb 27, 2017, 9:19:51 AM2/27/17
to SonarQube, ola.p...@mobenga.com
Hi,

thanks for the quick reply.
I have located the following rules that all cause the error:
  • "@NonNull" values should not be set to null
  • Conditions should not unconditionally evaluate to "TRUE" or to "FALSE"
  • Locks should be released
  • Loops should not be infinite
  • Null pointers should not be dereferenced
  • Optional value should only be accessed after calling isPresent()
  • Resources should be closed
  • Zero should not be a possible denominator
Hopefully they can help you solve the problem.

Regards 
Ola Persson
Reply all
Reply to author
Forward
0 new messages