picocli
picocli copied to clipboard
Picocli code gen throwing java.lang.ClassCastException: class com.sun.tools.javac.code.Attribute$UnresolvedClass
Following up from: https://github.com/remkop/picocli/issues/1137
I am still running in to this with picocli 4.6.1: https://gist.github.com/agibsonccc/0e90c40e765e417d927de3c35ee6fabc
I am using graalvm jdk 11: graalvm-ce-java11-21.2.0
Looking at the error (repeated full stack trace below):
FATAL ERROR: java.lang.ClassCastException: class com.sun.tools.javac.code.Attribute$UnresolvedClass cannot be cast to class com.sun.tools.javac.code.Attribute$Class (com.sun.tools.javac.code.Attribute$UnresolvedClass and com.sun.tools.javac.code.Attribute$Class are in module jdk.compiler of loader 'app')
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker$ValueVisitor.visitArray(AnnotationProxyMaker.java:192)
[ERROR] at jdk.compiler/com.sun.tools.javac.code.Attribute$Array.accept(Attribute.java:327)
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker$ValueVisitor.getValue(AnnotationProxyMaker.java:167)
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker.generateValue(AnnotationProxyMaker.java:145)
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker.getAllReflectedValues(AnnotationProxyMaker.java:104)
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker.generateAnnotation(AnnotationProxyMaker.java:90)
[ERROR] at jdk.compiler/com.sun.tools.javac.model.AnnotationProxyMaker.generateAnnotation(AnnotationProxyMaker.java:81)
[ERROR] at jdk.compiler/com.sun.tools.javac.code.AnnoConstruct.getAnnotation(AnnoConstruct.java:185)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.updateCommandSpecFromCommandAnnotation(AbstractCommandSpecProcessor.java:335)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.updateCommandSpecFromTypeElement(AbstractCommandSpecProcessor.java:276)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.access$100(AbstractCommandSpecProcessor.java:92)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor$1.visitType(AbstractCommandSpecProcessor.java:244)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor$1.visitType(AbstractCommandSpecProcessor.java:241)
[ERROR] at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.accept(Symbol.java:1447)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.buildCommand(AbstractCommandSpecProcessor.java:241)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.buildCommands(AbstractCommandSpecProcessor.java:226)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.tryProcess(AbstractCommandSpecProcessor.java:185)
[ERROR] at picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.process(AbstractCommandSpecProcessor.java:165)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:980)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:896)
in that stacktrace, to me the most interesting line is the last line of picocli code, which is this:
picocli.codegen.annotation.processing.AbstractCommandSpecProcessor.updateCommandSpecFromCommandAnnotation(AbstractCommandSpecProcessor.java:335)
Looking at what AbstractCommandSpecProcessor.java:335
does:
Command cmd = element.getAnnotation(Command.class);
So, getting the annotation class picocli.CommandLine.Command
results in a ClassCastException because (judging from Attribute$UnresolvedClass) the Command
class cannot be resolved.
My guess is that the picocli jar is not in the classpath, only the picocli-codegen jar is in the classpath. Can you confirm and try again after adding the picocli jar to the classpath for the annotation processor?
@agibsonccc did that solve the issue?
@remkop actually picocli was on the classpath. The only fix was removing codegen from the classpath. For now I just manually extracted the graalvm information I needed. I'll hope to add the codegen module back at a later date.
@agibsonccc I still suspect it is a build config issue. Can you post your maven or gradle config here?
@remkop let me see if I can build a minimal reproducer project for you to verify the issue.
Are you using Gradle? I had a similar issue once but it is a long time ago and I don't remember exactly, but it had to do with the classpath for the annotation processor being different from the classpath for the rest of the compilation.
I can imagine this error happening if --processor-path
only contains picocli-codegen
(but not picocli
).
You may be able to verify this by adding this snippet to your build.gradle
:
tasks.withType(JavaCompile) {
doFirst {
println "AnnotationProcessorPath for $name is ${options.getAnnotationProcessorPath().getFiles()}"
}
}
@remkop actually no. Just maven with picocli and codegen. You can actually see the project's reflect config json here: https://github.com/KonduitAI/konduit-serving/blob/master/konduit-serving-config-creator/src/main/resources/META-INF/native-image/reflect-config.json#L35
The pom including the relevant native image command line can be found here: https://github.com/KonduitAI/konduit-serving/blob/master/konduit-serving-config-creator/pom.xml#L190
You can kind of see why I would want to extract a minimal project for you. I'm only using a standard picocli 4.6.1 with the 2 dependencies, nothing crazy.
Okay great, access to your pom is helpful. Can you try adding the picocli dependency to the annotation processor path (line 177)? Something like this:
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.1</version>
</path>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.6.1</version>
</path>
</annotationProcessorPaths>
@agibsonccc did that solve the issue?
@agibsonccc did that solve the issue?
Well, it solved mine between your suggestions @remkop and the parent's reflect config. Thank you.
Hey folks sorry for the late reply: when I was trying this I was using the picocli docs pretty closely and still running in to this.
Hi @agibsonccc thanks for replying!
You mention the picocli docs, and that is also what I am interested in. The docs currently suggest this configuration:
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.2</version>
</path>
</annotationProcessorPaths>
I was wondering if the problem you encountered would be resolved if you changed that to this instead:
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.2</version>
</path>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.6.2</version>
</path>
</annotationProcessorPaths>
Have you had a chance to try that and what was the result?
Hey guys I ran into this issue with a different annotation processor.
It looks like this: https://bugs.openjdk.org/browse/JDK-8023548 but I have had annotation processors work fine and then suddenly fail with a similar error when doing refactoring or what not.
The issue is whatever class that is referenced in the annotation array better be available in the classpath or imported corrected. Otherwise instead of getting a compiler error about the class (symbol) not being found you get the bizarre annotation error from that bug.
So I don't know about picocli' annotations API but I'm betting it has an annotation that takes an array of classes similar to this one:
@Retention(SOURCE)
@Documented
@Target(TYPE)
public @interface MetaInfServices {
Class<?>[] value() default void.class;
}
If I say did:
@MetaInfServices(SomeClassMissingFromClasspath.class)
You will get the bizarro exception.
So I'm betting the bug filer has some classpath issues.
@agentgt Thanks for letting us know. I don't think there's anything that can be done about this in the picocli library, but please let me know if I am incorrect about that.
@remkop that is correct that there is nothing the lib can do. I was merely knowledge sharing.
@agentgt @remkop I haven't been able to look at this in a while but haven't bumped in to this in a while. I would go ahead and just close this. If someone else runs in to this at least they'll find this github issue.