@Supported design issues (original) (raw)

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 way.

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)
@Supported(true) @Deprecated
@Supported(false)
<gone>

(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.

Understood.

...

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; }

Yuck.

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.

Agreed.

- 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.



More information about the core-libs-dev mailing list