Annotation type first encountered during ClassReader annotation parsing has wrong module?

Jan Lahoda jan.lahoda at oracle.com
Fri Jul 14 08:05:33 UTC 2023


Hello Laird,


I am afraid a reproducible case is likely needed for this. I tried a 
simple testcase, where a use in module "use" uses an annotation from 
different module "lib", and the usages is from classfile:

https://github.com/lahodaj/jdk/blob/e74368cb72790a399f3bb28c0dde2146d015757e/test/langtools/tools/javac/modules/AnnotationsAndMultipleModules.java


Also, please note that the semantics of "Symtab.enterClass(ModuleSymbol 
msym, Name flatname)" is not "create a class called flatname in module 
msym", but "create a class called flatname accessible from module msym". 
This method follows the module rules, and looks into the modules the 
given module is reading, to find the correct package in the correct 
module to place the class. (It will fallback to placing the class into 
the given module, if there's no dependency where it would belong, which 
might be cause e.g. by improperly setup modules.)


Jan


On 13. 07. 23 1:37, Laird Nelson wrote:
> I'm noticing that the type and element information for an 
> AnnotationMirror's annotation type is erroneous when read from a class 
> file via ClassReader in certain situations.
>
> Specifically, consider:
> * a module M with
> * a class p.A with
> * a method B annotated with
> * a runtime visible annotation q.C where
> * q (and therefore C) is not contained by M:
>
> package p; // enclosed by module M
> public class A {
>   @q.C // q is not enclosed by M
>   public void B() {}
> }
>
> Assuming I use javax.lang.util.Elements to get the ExecutableElement 
> corresponding to B, this should (it seems to me) succeed (q.C's type's 
> kind should be DECLARED):
>
> TypeElement e = elements.getTypeElement("p.A");
> // boring recipe for getting ExecutableElement for B from e omitted 
> for brevity
> assert TypeKind.DECLARED == 
> executableElementForB.getAnnotationMirrors().get(0).getAnnotationType().getKind();
>
> Instead it fails because the TypeKind in question is TypeKind.ERROR.  
> (Recall this is not source-related; I'm asking javax.lang.model.* to 
> read valid already-compiled class files.)
>
> From debugging into the compiler (I am a not very bright bull in a 
> china shop), it seems to my naïve eyes that when the ClassSymbol for 
> q.C is created as part of annotation bytecode reading, ClassReader 
> assumes incorrectly that the module that should enclose q.C is M (see 
> https://github.com/openjdk/jdk/blob/jdk-20%2B36/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java#L535-L550, 
> and note that at #enterClass(Name)-time currentModule is M 
> (https://github.com/openjdk/jdk/blob/jdk-20%2B36/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java#L2468).
>
> At any rate, the classfile attribute for the ClassSymbol for q.C when 
> q.C is encountered/created via this annotation-bytecode-reading 
> pathway is never set (probably because M is asked for its classes or 
> packages or something and q.C is not among them, correctly, so the 
> completion machinery doesn't know how to get it?), and that nullness 
> seems to be the root cause for the TypeKind.ERROR being reported.
>
> Also of note: if I ask for the TypeElement corresponding to q.C 
> directly (via, say, elements.getTypeElement("q.C")) its ElementKind 
> and associated TypeKinds are correct.
>
> The situation in which I encountered this is rather convoluted so I 
> don't have a simple executable reproducer ready to hand, but all the 
> information that I know of is here.
>
> Shall I file a bug, or work with someone offline, or is this expected 
> behavior, or…? Thanks for everyone's time.
>
> Best,
> Laird


More information about the compiler-dev mailing list