Search code examples
javajava-8checker-framework

Does '+' in an annotation name have some special meaning?


I was looking at the bytecode of the .jar file of the custom annotated jdk-8 in the central maven repository supplied by the Checker Framework.

There I noticed some invalid Java Code in Object.class and Class.class files. When I loaded the jar in Eclipse it was an annotation with the following syntax:

@jdk.Profile+Annotation(value=(int) 1)
public class java.lang.Object {

Now, as far as my knowledge goes, this annotation name is invalid Java. But, I'm assuming it might mean something to the compiler (similar to the names that the compiler assigns to anonymous classes). I'm not sure what and I couldn't find anything about it on searching online either. Hence, the query.

Any help is appreciated.


Solution

  • I don't think it has any special meaning. It's a system annotation related to JEP 161 which added additive "profiles" so that you can run an app on a subset of the JRE. It is added programatically so it does not need to adhere to the rules of the grammar.

    Searching the OpenJDK bug tracker for this JEP turned up the commit where the "synthetic" annotation is added.

    It looks as though the precedent was already established for a sun.Proprietary+Annotation and they just followed the convention.

    I suspect that the reason the Sun annotation was named that way has been lost to the annals of time - it predates Java 6, before the code was open source.

    I also found a commit to jdeps where they're parsing these annotations where they do not give any importance to the manner in which they are named; they just use the fully qualified name for both.


    You too can start using illegal type identifiers -- no career at Oracle required!

    final DynamicType.Unloaded<? extends Annotation> unloaded = new ByteBuddy()
        .with(TypeValidation.DISABLED)
        .makeAnnotation()
        .name("jdk.Profile+Annotation")
        .make();
    
    final DynamicType.Loaded<? extends Annotation> loaded = unloaded.load(Test.class.getClassLoader());
    final Class<? extends Annotation> myBadlyNamedAnnotation = loaded.getLoaded();
    
    System.out.println(myBadlyNamedAnnotation);