Weird Java error when trying to use a custom SubscriptionVisitor

Hello everyone,

I have written some code to detect false-positive issues of a sonar rule. (relates to this thread.). It works fine when I run it as a standalone java program.

Then I included this in a plugin to execute via a PostProjectAnalysisTask so I can run this within the Sonarqube server. Server starts up fine but when I run an analysis I get a strange java error.

My code:

Path srcFile = Files.createTempFile("sonar-src-", ".java");
Files.write(srcFile, src.getBytes(), StandardOpenOption.WRITE);
InputFile inputFile = new GeneratedFile(srcFile);
JavaAstScanner scanner = new JavaAstScanner(null);
scanner.setVisitorBridge(new VisitorsBridge(new MethodVisitor(sonarIssueService, issue, nullableEntity)));
scanner.scan(Collections.singleton(inputFile));
public class MethodVisitor extends SubscriptionVisitor {
    @Override
    public List<Kind> nodesToVisit() {
        return Collections.singletonList(Kind.METHOD);
    }

    public void visitNode(@Nonnull Tree tree) {
        tree.accept(new StatementVisitor(sonarIssueService, issue, nullableEntity));
    }
}
public class StatementVisitor extends BaseTreeVisitor {
    // my logic here
}

Java error:

2024.06.07 08:32:57 ERROR ce[682c0e66-06ab-45eb-a75d-49e461e4b6cd][o.s.c.t.s.ComputationStepExecutor] Execution of listener failed
java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/sonar/java/model/VisitorsBridge.lambda$filterVisitors$0(Lorg/sonar/java/model/VisitorsBridge$IssuableSubscriptionVisitorsRunner;Ljava/util/List;Lorg/sonar/plugins/java/api/JavaCheck;)V @14: invokevirtual
  Reason:
    Type 'org/sonar/plugins/java/api/IssuableSubscriptionVisitor' (current frame, stack[1]) is not assignable to 'org/sonar/java/ast/visitors/SubscriptionVisitor'
  Current Frame:
    bci: @14
    flags: { }
    locals: { 'org/sonar/java/model/VisitorsBridge$IssuableSubscriptionVisitorsRunner', 'java/util/List', 'org/sonar/plugins/java/api/JavaCheck', 'org/sonar/plugins/java/api/IssuableSubscriptionVisitor' }
    stack: { 'org/sonar/java/model/VisitorsBridge$IssuableSubscriptionVisitorsRunner', 'org/sonar/plugins/java/api/IssuableSubscriptionVisitor' }
  Bytecode:
    0000000: 2cc1 01ca 9900 102c c001 ca4e 2a2d b601
    0000010: cca7 0019 2cc1 00cd 9900 122c c000 cd3a
    0000020: 042b 1904 b900 8702 0057 b1
  Stackmap Table:
    same_frame(@20)
    same_frame(@42)

	at com.example.testing.issue.FalsePositiveIssueDetector.verifyIssue(FalsePositiveIssueDetector.java:90)
	at com.example.testing.issue.FalsePositiveIssueDetector.processSonarIssue(FalsePositiveIssueDetector.java:60)
	at java.base/java.util.ArrayList.forEach(Unknown Source)
	at com.example.testing.issue.PostAnalysisIssueVerifier.finished(PostAnalysisIssueVerifier.java:56)
	at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.executeTask(PostProjectAnalysisTasksExecutor.java:101)
	at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.finished(PostProjectAnalysisTasksExecutor.java:92)
	at org.sonar.ce.task.step.ComputationStepExecutor.executeListener(ComputationStepExecutor.java:89)
	at org.sonar.ce.task.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:61)
	at org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor.process(ReportTaskProcessor.java:75)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.executeTask(CeWorkerImpl.java:212)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.run(CeWorkerImpl.java:194)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.findAndProcessTask(CeWorkerImpl.java:160)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$TrackRunningState.get(CeWorkerImpl.java:135)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:87)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:53)
	at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:131)
	at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:76)
	at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:82)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)

My efforts to figure this out had no luck so far. Has any of you seen something like this? Any clues?

Some useful info:

  • Sonarqube version: v10.5.1 (Java 17.0.11)
  • Local javac version: 17.0.9
  • I had to bundle org.sonarsource.java:java-frontend with the plugin as I’m using an org.sonar.java.model.GeneratedFile as input file. Otherwise I get a CNF exception.

Thank you,
Bhathiya

On a related note, it’s weird why it gives me CNF for org.sonar.java.ast.JavaAstScanner as well as for org.sonar.java.model.GeneratedFile if I don’t bundle org.sonarsource.java:java-frontend:7.33.0.35775 while the server already have the sonar-java-plugin-7.33.0.35775.jar. Is there any explanations for this? (I’m digging up on this because I suspect there’s a chance a duplicated runtime dependency to cause above issue.)

Hello @Bhathiya,

It seems that the error is due to the fact that you are using classes that are not part of the public API of SonarJava (SubscriptionVisitor and VisitorsBridge). Can you please try making MethodVisitor a subclass of IssuableSubscriptionVisitor instead of SubscriptionVisitor? If the error persists, could you please provide a reproducer or a little more information about the structure of your project?

Best,
Valentin