@Supported design issues

mark.reinhold at oracle.com mark.reinhold at oracle.com
Fri Mar 15 21:12:49 UTC 2013

2013/3/4 2:58 -0800, joe.darcy at oracle.com:
> On 02/28/2013 11:31 AM, mark.reinhold at oracle.com wrote:
>> 2013/2/23 5:10 -0800, joe.darcy at oracle.com:
>>> Having Supported take a boolean value both allows the explicit statement
>>> that an item is not supported as well as providing a possible transition
>>> path from Supported(true) to Supported(false) to removed.
>> Okay.  In that scenario what's the role of the existing @Deprecated
>> annotation?
> @Deprecated generally applies to all clients of an API. I don't think 
> people tend to associate potential removal of an API with deprecation 
> because we haven't (yet) removed any deprecated Java SE APIs from the 
> platform since to date we have placed a higher value on preserving  
> binary compatibility.

I'm continually surprised by developers I meet at conferences who
(sometimes angrily) demand that deprecated APIs be removed, so I think
the reality is a mixed bag -- not that it matters a great deal either

What I'm trying to understand is, for a JDK API that's @Supported(true)
in one or more releases, what's the recommended protocol for removing
it?  Perhaps something like this?

    @Supported(true) @Deprecated

(Time flows downward.)

Or does @Supported(false) happen when @Deprecated is applied?

Or will usage vary?

> The deprecated-in-JDK-7 and JDK-specific apt API was removed in JDK 8, 
> but that is the only removal of a deprecated API from the JDK I'm aware 
> of offhand.

I suspect that's correct.

> The jdk.Supported annotation is mostly a statement to users outside of 
> the JDK itself.


>> ...
>> I'm still wondering whether marking a package "@Supported(true)" means
>> that I can use "@Supported(false)" on some of its member types.  That
>> would be convenient for cases such as the JMX OSMBeanFactory class that
>> Alan mentioned.
> If a package has a mixture of supported and non-supported types, I would 
> say it should either *not* have a @jdk.Supported annotation itself, or 
> if the types in the package were predominately one value or another, 
> then the package annotation should match the prevailing value of the types.
> Since types have a more concrete existence then packages, I regard the 
> jdk.Supported information on package-info files to have a higher mixture 
> of informative versus normative sentiment compared to the annotation on 
> types.

If we're going to go to the trouble of defining an annotation for this,
and then sprinkle that annotation throughout our code, shouldn't we give
it as precise a meaning as possible?  It'd be a shame for @Supported (or
whatever it turns out to be) to have no more authoritative value than,
say, the @since javadoc tag.

>>> ...
>> What I don't understand is how doing all this with an annotation would
>> be any harder to circumvent than what we have today.  Are you proposing
>> to do something stronger than issue a compiler warning when people try
>> to use an unsupported API?
> The ct.sym mechanism we have today is compile-time only and the 
> mechanism and all its warnings can be circumvented by adding a single 
> option to javac; the option is described on stackoverflow, amongst other 
> places. Therefore, it is fairly easy for someone to claim "but I didn't 
> know" in regards to the status of a JDK-specific API.

Well, sure.

> Since any jdk.Supported annotations applied to types are more localized 
> and more specific ("*this* type is or is not supported / stable / etc.") 
> it is both easier for JDK developers to made incremental changes to the 
> JDK code base and is it also easier for users of those types to see what 
> is going on since any inspection of the types can reveal the annotation 
> value.

Agreed, but I was trying to understand how the annotation-based system
would be harder to "cirvumvent", at either compile time or run time.

>> ...
>> Even if we think we only need two explicit levels today, a design that
>> admits expansion is preferable to one that forever limits us to just two
>> values.  An annotation that takes an enum, to which we can add values
>> over time, would be more future-proof.
> Technically, it would be possible to evolve a boolean-valued annotation 
> to one that included a non-boolean value as well by adding a new method 
> that had a default to the annotation type. For example
> // Version 1
> @interfaced Supported {
>      boolean value() default true;
> }
> // Version 2
> @interface Supported {
>      boolean value() default true;
>      Stability stability() default STABLE;
> }


> However, if what we eventually want to capture is "stability level" 
> rather than supported-ness than having a single stability value from the 
> start would of course be preferable.
> That said, it terms of the exercise of going over the inventory of 
> existing types, I think it can be helpful to at first be constrained to 
> making a binary supported / not-supported determination to avoid the 
> temptation to overuse a middle-of-the-road value like EVOLVING.
> Types that don't fit well into supported / not-supported classification 
> can help drive what other distinctions are useful to make.


>>>> - The retention policy of the annotation is RUNTIME.  Is that really
>>>>   what we want?  I'd have expected CLASS.
>>> CLASS is not very helpful (and certainly not a helpful default). A
>>> CLASS-retention annotation can be reliably used at the compile-time of
>>> other code. For the use case of Supported, I think it is more helpful to
>>> allow runtime querying of the property.
>> What run-time use cases do you have in mind?
> Allowing class loaders and other run-time tools to query the annotation 
> value and take some action, like log a warning or potentially refuse to 
> link.

Okay, that sounds plausible.

> ...
> As an aside, going forward I think we should make greater use of the 
> "jdk.*" namespace for JDK-specific types. The JDK codebase has outlasted 
> Sun Microsystems (R.I.P.) and therefore the natural lifetime of 
> "com.sun.*." APIs. The JDK has also outlasted both of Sun Microsystems' 
> ticker symbols (SUNW, and JAVA); as I understand their conventions, 
> ticker symbols are a preferred component of Solaris package names. The
> "jdk" name will be appropriate as long as the JDK is around.

I have long supported this position -- jdk.* is the place to be for new
non-Platform, non-proprietary APIs.

>> I did just notice that the annotation's source file is in the langtools
>> repo rather than the jdk repo.  What's the rationale for that?  I think
>> most JDK developers would expect to find it in the jdk repo.
> As covered in other responses, while the jdk repo is the natural home, 
> langtools was for bootstrapping reasons.

Hmm.  Okay.

- Mark

More information about the core-libs-dev mailing list