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

Joseph D. Darcy joe.darcy at oracle.com
Fri Jul 14 04:19:44 UTC 2023


Some additional context, to construct annotations from a class file, 
either runtime via core reflection or at compile-time for javac, at some 
point a name -> annotation type lookup needs to be performed. The name 
of the annotation type is what is represented in the class file along 
with the actual data for the methods of the annotation to return.

At runtime it is *not* an error if the annotation type for an annotation 
is not found, no annotation for that type is returned.

If the "path"/environment to perform the annotation type name -> 
annotation type is not configured to include the annotation type, it 
won't be found.

Without looking at the javac implementation, it is certainly feasible 
that the environment to do the annotation type name mapping is not 
correctly configured in a case like that. For example, any public 
annotations in java.base should always be accessible even to code in 
other modules.

HTH,

-Joe

On 7/12/2023 4:37 PM, 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