Error during SonarScanner execution java.lang.NoClassDefFoundError: org/sonar/java/model/JavaTree

What are you trying to accomplish?

  • Support a new language? - No
  • Extend an existing one? Which one? - Yes, extending java:S2077
  • Something else? - trying to add more method names to it.

What’s your specific coding challenge in developing your plugin?
It is reporting and issues as expected. It is highlighting the associated, reassigned values of an identifier variable at secondary locations of a different method call.

And, if relevant, please share the code that’s giving you problems:

I am able to build the plugin, but it is giving me following error in runtime.

09:46:45.251 INFO: JavaTestClasspath initialization (done) | time=3ms
09:46:45.273 INFO: Server-side caching is enabled. The Java analyzer will not try to leverage data from a previous analysis.
09:46:45.300 INFO: Using ECJ batch to parse 1 Main java source files with batch size 214 KB.
09:46:45.410 DEBUG: 'Action.java' generated metadata with charset 'UTF-8'
09:46:45.601 INFO: Starting batch processing.
09:46:47.719 INFO: The Java analyzer cannot skip unchanged files in this context. A full analysis is performed for all files.
09:46:48.831 DEBUG: [SE] Loaded 227 hardcoded method behaviors.
09:46:49.632 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method getCommaSeparatedAddresse#3100 in class Action
09:46:50.197 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method validateEmailsForJasper#3157 in class Action
09:46:50.644 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method addEmailInfoToDB#1698 in class Action
09:46:51.488 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method getReportParameters#648 in class Action
09:46:51.800 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method sendReport#1058 in class Action
09:46:52.490 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method execute#76 in class Action
09:46:52.896 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method addAltFaxInfoToDB#1475 in class Action
09:46:53.471 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method addFaxInfoToDB#1991 in class Action
09:46:53.784 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method getPCMReportParams#449 in class Action
09:46:53.996 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method handlePCM#346 in class Action
09:46:54.624 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method getReportJobID#1131 in class Action
09:46:55.618 INFO: 50% analyzed
09:46:55.865 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method managePreview#1261 in class Action
09:46:57.379 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method addColdStorageToDB#2067 in class Action
09:46:58.477 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method manageColdStorage#2587 in class Action
09:46:59.247 DEBUG: Could not complete symbolic execution: reached limit of 16000 steps for method handleDocumentMerge#2923 in class Action.java
09:46:59.651 DEBUG: Analysis time of Action.java (12712ms)
09:46:59.654 INFO: Did not optimize analysis for any files, performed a full analysis for all 1 files.
09:46:59.674 INFO: ------------------------------------------------------------------------
09:46:59.676 INFO: EXECUTION FAILURE
09:46:59.676 INFO: ------------------------------------------------------------------------
09:46:59.678 INFO: Total time: 23.692s
09:46:59.818 INFO: Final Memory: 21M/80M
09:46:59.819 INFO: ------------------------------------------------------------------------
09:46:59.820 ERROR: Error during SonarScanner execution
java.lang.NoClassDefFoundError: org/sonar/java/model/JavaTree
        at ca.cmic.rules.SQLInjectionCheck.lambda$visitNode$0(SQLInjectionCheck.java:117)
        at java.base/java.lang.Iterable.forEach(Unknown Source)
        at ca.cmic.rules.SQLInjectionCheck.visitNode(SQLInjectionCheck.java:115)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.lambda$visit$6(VisitorsBridge.java:452)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.lambda$forEach$9(VisitorsBridge.java:468)
        at org.sonar.java.model.VisitorsBridge.runScanner(VisitorsBridge.java:265)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.forEach(VisitorsBridge.java:468)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:454)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visitChildren(VisitorsBridge.java:438)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.visit(VisitorsBridge.java:458)
        at org.sonar.java.model.VisitorsBridge$IssuableSubscriptionVisitorsRunner.scanFile(VisitorsBridge.java:416)
        at org.sonar.java.model.VisitorsBridge.lambda$runScanner$1(VisitorsBridge.java:260)
        at org.sonar.java.model.VisitorsBridge.runScanner(VisitorsBridge.java:265)
        at org.sonar.java.model.VisitorsBridge.runScanner(VisitorsBridge.java:260)
        at org.sonar.java.model.VisitorsBridge.visitFile(VisitorsBridge.java:243)
        at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:132)
        at org.sonar.java.JavaFrontend.scanAsBatchCallback(JavaFrontend.java:247)
        at org.sonar.java.JavaFrontend.lambda$scanBatch$0(JavaFrontend.java:238)
        at org.sonar.java.model.JParserConfig$Batch$1.acceptAST(JParserConfig.java:181)
        at org.eclipse.jdt.core.dom.CompilationUnitResolver.resolve(CompilationUnitResolver.java:1143)
        at org.eclipse.jdt.core.dom.CompilationUnitResolver.resolve(CompilationUnitResolver.java:739)
        at org.eclipse.jdt.core.dom.ASTParser.createASTs(ASTParser.java:1049)
        at org.sonar.java.model.JParserConfig$Batch.parse(JParserConfig.java:165)
        at org.sonar.java.JavaFrontend.scanBatch(JavaFrontend.java:238)
        at org.sonar.java.JavaFrontend.scanInBatches(JavaFrontend.java:228)
        at org.sonar.java.JavaFrontend.scanAsBatch(JavaFrontend.java:195)
        at org.sonar.java.JavaFrontend.scan(JavaFrontend.java:170)
        at org.sonar.plugins.java.JavaSensor.execute(JavaSensor.java:113)
        at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:64)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:88)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:79)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.scan.SpringModuleScanContainer.doAfterStart(SpringModuleScanContainer.java:82)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scan(SpringProjectScanContainer.java:403)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scanRecursively(SpringProjectScanContainer.java:399)
        at org.sonar.scanner.scan.SpringProjectScanContainer.doAfterStart(SpringProjectScanContainer.java:368)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167)
        at org.sonar.scanner.bootstrap.SpringGlobalContainer.doAfterStart(SpringGlobalContainer.java:137)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167)
        at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:72)
        at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:66)
        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
        at com.sun.proxy.$Proxy0.execute(Unknown Source)
        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
        at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:112)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:75)
        at org.sonarsource.scanner.cli.Main.main(Main.java:61)
Caused by: java.lang.ClassNotFoundException: org.sonar.java.model.JavaTree
        at org.sonar.classloader.ParentFirstStrategy.loadClass(ParentFirstStrategy.java:39)
        at org.sonar.classloader.ClassRealm.loadClass(ClassRealm.java:87)
        at org.sonar.classloader.ClassRealm.loadClass(ClassRealm.java:76)

Initial changes were

static List<String> SQL_QUERY_METHODS = Arrays.asList("createCallableStatement", "createPreparedStatement", "createStatement", "createViewObjectFromQueryStmt", "setWhereClause");

Supplied additional list of methodNames to check for.
Which is good.
BUt now the problem is highlighting the reassigned values of identifier variable at secondary locations which belongs to a different method call.

So, to solve this I am trying to limit the scope of check in between line numbers of suspicious method calls identified.

I made some changes to the rule implementation for that.
But it was giving me runtime errors as shown above.

Note:
EXECUTION FAILURE : The analysis failed, and the error message indicates a NoClassDefFoundError for the class **org/sonar/java/model/JavaTree** . This typically means that this class was expected to be in the classpath during the runtime of the analysis, but it was not found.
I guess fix for this will solve my problem.

Please advise how to achieve my goal.

For your reference:

 @Override
    public void visitNode(Tree tree) {
        if(tree.is(Tree.Kind.METHOD_INVOCATION)) {
            MethodInvocationTree mit = (MethodInvocationTree) tree;
            boolean result = anyMatch(tree);
            boolean queryMethodResult = anyQueryMethod(mit.methodSelect().lastToken().text());
            if(result || queryMethodResult) {
                Arguments args = mit.arguments();
                if(args != null) {
                    args.forEach(ex -> {
                        if(ex.symbolType().is(STRING_CLASS)) {
                            lastSuspiciousMethodLine = ((JavaTree) mit).getLine();
                            checkExpressionTree(ex);
                        }
                    });
                }
            }

line 117 : from my rule class is

 lastSuspiciousMethodLine = ((JavaTree) mit).getLine();

this JavaTree is not found during runtime.

Thanks
vsk

Hi vsk,

I’ve edited your post to remove the summary markdown so I could apply code formatting. For some reason, I couldn’t simply add the code formatting in the summary blocks; it wouldn’t render.

Regarding your question, are you sure JavaTree is a publicly available API? There’s a good bit in the Java engine that’s not available to plugin authors, and if you’re starting from a native rule it’s quite likely it’s using some private APIs.

 
Ann

Please advise if there is an alternative way to achieve this without involving JavaTree.

Thanks
vsk

Hello @shiva_sq ,

Did you have a look at the tutorial about writing custom rules for the Java analyzer (Custom Rules 101)? I’m asking because there is a part in the tutorial that is explicit about this, and you might have missed it (What you can use and what you can’t). If this part this not clear to you, we might want to update it a bit to also give an example of classes NOT to use and so we would appreciate your feedback.

In this context, the org.sonar.java.model.JavaTree is definitely not part of org.sonar.plugins.java.api package, and therefore not available at runtime. We don’t intend to expose it, this class is purely for internal use. Ultimately, that’s indeed what is causing your issue. You can not use this class in your custom rules.

Now, if you are only interested in identifying the line of the method invocation, then this code should do the job, and it relies entirely on the official API:

mit.firstToken().range().start().line();

Hope this helps,
Michael

Thanks for the suggestion.
My goal is not just to “identifying the line”, but I want to limit the scope as I mentioned

Please let me know if you have any alternate way to do that.

Thanks
vsk

Sorry, but I’m really not sure to understand what you are asking. You faced an issue with JavaTree causing errors at analysis time. This should not happen if you only use classes inside the provided API.

Regarding “highlighting the reassigned values of identifier variable at secondary locations which belongs to a different method call”, this is not at all trivial, and you will have to manually explore all identifiers.

To do so, from an identifier, you can go to its symbol(), and look at its usages(). There, you will have to check manually if it’s within the boundaries that you expect (between some lines, or other constraints). The logic to take such a decision is up to you to find.

It would help if you could provide an example of what you try to achieve, with some real code.

Hope this helps,
Michael