8008662: Add @jdk.Supported to JDK-specific/supported API
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs. I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported". Specifically I'm proposing to add it to: - Java Debug Interface (com.sun.jdi) - Attach API (com.sun.tools.attach) - SCTP API (com.sun.nio.sctp) - HTTP server API (com.sun.net.httpserver) - Management extensions (com.sun.management) - JDK-specific API to JAAS (com.sun.security.auth) - JDK-specific JGSS API (com.sun.security.jgss) The javadoc for all of these is generated as part of the regular JDK "docs" build and so shouldn't be controversial. There are a number of other candidates in com.sun with murkier status that I've stayed clear of for now. The webrev with the changes is here: http://cr.openjdk.java.net/~alanb/8008662/webrev/ In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java. In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that. Otherwise this is mostly mechanical and the patch file is easier to review that the webrev. -Alan [1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
Well, that was quite a few files to have to go through :-) Looks fine On Feb 21, 2013, at 1:46 PM, Alan Bateman wrote:
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs.
I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported". Specifically I'm proposing to add it to:
- Java Debug Interface (com.sun.jdi) - Attach API (com.sun.tools.attach) - SCTP API (com.sun.nio.sctp) - HTTP server API (com.sun.net.httpserver) - Management extensions (com.sun.management) - JDK-specific API to JAAS (com.sun.security.auth) - JDK-specific JGSS API (com.sun.security.jgss)
The javadoc for all of these is generated as part of the regular JDK "docs" build and so shouldn't be controversial. There are a number of other candidates in com.sun with murkier status that I've stayed clear of for now.
The webrev with the changes is here:
http://cr.openjdk.java.net/~alanb/8008662/webrev/
In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java.
In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that.
Otherwise this is mostly mechanical and the patch file is easier to review that the webrev.
-Alan
[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037 Oracle Java Engineering 1 Network Drive Burlington, MA 01803 Lance.Andersen@oracle.com
On 2/21/2013 10:46 AM, Alan Bateman wrote:
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs.
I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported".
It's nice to be able to mark what is supported vs unsupported in the com.sun namespace since there are a mix of supported and unsupported APIs.
[...] The webrev with the changes is here:
Looks good to me.
In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java.
In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that.
I wasn't aware of the unsupported com.sun.management.OSMBeanFactory class being included in the javadoc. I think that can be fixed and I'll file a bug and hopefully we can clean that up. Mandy
Otherwise this is mostly mechanical and the patch file is easier to review that the webrev.
-Alan
[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
On 02/21/2013 10:46 AM, Alan Bateman wrote:
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs.
I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported". Specifically I'm proposing to add it to:
To add some more context here, there are various APIs outside of the Java SE namespaces (java.* and javax.*) that are shipped with the JDK. Some of these APIs and meant to be called by normal users of the JDK and evolve under essentially the same general evolution policy [1] as the SE API. Call such non-SE APIs in the JDK "supported." One example of such a supported API is the javac Tree API in com.sun.source.* JDK 7: http://docs.oracle.com/javase/7/docs/jdk/api/javac/tree/index.html JDK 8: http://download.java.net/jdk8/docs/jdk/api/javac/tree/index.html However, the com.sun.* subpackages are a mix of APIs that are supported as described above as well as APIs that are not supported. APIs that are not supported are *not* meant to be called by normal users of the JDK and can have a very different evolution policy, up to and including deletion from the JDK in a update release. The goal of adding the @Supported annotations is to allow these API categories to be more easily distinguished from each other, including enabling tools to check that @Supported(value=false) APIs are not referenced. The jdk.Supported annotation can be applied to both types and packages; it is *not* intended to allow modeling of supported-ness down to only a subset of methods of a type. In other words, if @jdk.Supported is applied to something, it is meant to refer to the whole entity, either all the parts of a type or all the types in a package. To make the information more prominent and easier to find, I recommend applying the annotation to both all the types in a package and the package itself, which is what I've done in the tree API. [2] In Alan's case below, I would not apply the annotation to a package if the package had a mix of supported and unsupported types. Cheers, -Joe [1] http://cr.openjdk.java.net/~darcy/OpenJdkDevGuide/OpenJdkDevelopersGuide.v0.... [2] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/011cf7e0a148
- Java Debug Interface (com.sun.jdi) - Attach API (com.sun.tools.attach) - SCTP API (com.sun.nio.sctp) - HTTP server API (com.sun.net.httpserver) - Management extensions (com.sun.management) - JDK-specific API to JAAS (com.sun.security.auth) - JDK-specific JGSS API (com.sun.security.jgss)
The javadoc for all of these is generated as part of the regular JDK "docs" build and so shouldn't be controversial. There are a number of other candidates in com.sun with murkier status that I've stayed clear of for now.
The webrev with the changes is here:
http://cr.openjdk.java.net/~alanb/8008662/webrev/
In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java.
In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that.
Otherwise this is mostly mechanical and the patch file is easier to review that the webrev.
-Alan
[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
On Thu, Feb 21, 2013 at 6:16 PM, Joe Darcy <joe.darcy@oracle.com> wrote:
However, the com.sun.* subpackages are a mix of APIs that are supported as described above as well as APIs that are not supported.
I was under the impression that the general rule was that all of com.sun.* fell under the "jdk supported" umbrella, and the level of support was the distinction between sun.com.* and sun.* . In any case, it would be good if there was a single canonical place that documented the various levels of support with subtle distinctions, including java.* vs. javax.*, endorsed standards, com.sun.* vs. sun.* vs. jdk.*, and recommendations for where non-Oracle vendor extensions should go. Is the jdk.Supported annotation itself part of Java SE? Should third-party vendor extensions that are "supported" for public use by the third-party use jdk.Supported? What about the X's in hotspot flags and the java tools command line interfaces?
On 22/02/2013 14:06, Martin Buchholz wrote:
I was under the impression that the general rule was that all of com.sun.* fell under the "jdk supported" umbrella, and the level of support was the distinction between sun.com.* and sun.* .
com.sun is a mixed bag. There are lots of com.sun.*.internal that are clearly JDK internal/implementation/stay-away but several useful and documented APIs are in com.sun too (the JDK build generates the javadoc for these). In addition there are several APIs with murkier pasts, transitional APIs for areas that previous had a life as a standalone technology before coming into the JDK. -Alan.
Hi Martin, On 2/22/2013 6:06 AM, Martin Buchholz wrote:
On Thu, Feb 21, 2013 at 6:16 PM, Joe Darcy <joe.darcy@oracle.com <mailto:joe.darcy@oracle.com>> wrote:
However, the com.sun.* subpackages are a mix of APIs that are supported as described above as well as APIs that are not supported.
I was under the impression that the general rule was that all of com.sun.* fell under the "jdk supported" umbrella, and the level of support was the distinction between sun.com.* and sun.* .
Alan has previously replied on the varied supported-ness found in com.sun.*.
In any case, it would be good if there was a single canonical place that documented the various levels of support with subtle distinctions, including java.* vs. javax.*, endorsed standards, com.sun.* vs. sun.* vs. jdk.*, and recommendations for where non-Oracle vendor extensions should go. Is the jdk.Supported annotation itself part of Java SE?
No, the jdk.Supported annotation type is part of the JDK (currently living in the langtools repo): http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/56dfafbb9e1a/src/share/c... As you can see, the jdk.Supported type itself has a @jdk.Supported annotation :-)
Should third-party vendor extensions that are "supported" for public use by the third-party use jdk.Supported?
No; as I envision it, the jdk.Supported annotation is only meant to convey supported-ness in the JDK of parts of the JDK.
What about the X's in hotspot flags and the java tools command line interfaces?
The policy around command line interfaces is unchanged; the interfaces are mostly stable, but the more X's are in a flags name, the less stable it can be. -Joe
Hi Joe, On Fri, Feb 22, 2013 at 11:19 AM, Joe Darcy <joe.darcy@oracle.com> wrote:
Should third-party vendor extensions that are "supported" for public use by the third-party use jdk.Supported?
No; as I envision it, the jdk.Supported annotation is only meant to convey supported-ness in the JDK of parts of the JDK.
Depends on what you mean by "JDK". Suppose the icedtea project added a public "supported" method usesSystemZlib(). It would be good to provide guidance what package to put this in (org.classpath.* ?) and how to indicate level of support (by the icedtea project). Suppose the IcedTea project decided to officially support sun.misc.Unsafe. Would they do this by adding jdk.Supported annotation to their version of Unsafe.java, even if their upstream chose not to? What about the X's in hotspot flags and the java tools command line interfaces?
The policy around command line interfaces is unchanged; the interfaces are mostly stable, but the more X's are in a flags name, the less stable it can be.
We all learned this by indoctrination from the local sensei greybeard, but where is it documented for the wider world? Perhaps Supported isn't a binary thing, but needs to capture different levels of support? Solaris has had such support levels. A "beta" ("laba", "experimental") support level is very useful for introducing new technology. It's a very hard problem, especially in a 1000 flowers world.
Hi Martin, On 2/22/2013 1:40 PM, Martin Buchholz wrote:
Hi Joe,
On Fri, Feb 22, 2013 at 11:19 AM, Joe Darcy <joe.darcy@oracle.com <mailto:joe.darcy@oracle.com>> wrote:
Should third-party vendor extensions that are "supported" for public use by the third-party use jdk.Supported?
No; as I envision it, the jdk.Supported annotation is only meant to convey supported-ness in the JDK of parts of the JDK.
Depends on what you mean by "JDK". Suppose the icedtea project added a public "supported" method usesSystemZlib(). It would be good to provide guidance what package to put this in (org.classpath.* ?) and how to indicate level of support (by the icedtea project).
Suppose the IcedTea project decided to officially support sun.misc.Unsafe. Would they do this by adding jdk.Supported annotation to their version of Unsafe.java, even if their upstream chose not to?
For some definition of "JDK", IcedTea is "JDK" too since they provide a JDK distribution, one at least a little distinct from plain OpenJDK and also distinct from OracleJDK. The long-standing problem I wanted to address was clearly indicating whether or not the upstream code in shared JDK 8 sources was regarded as a public API or not. So I don't think it would necessarily be inappropriate for a hypothetical org.classpath type to use jdk.Supported, but I wasn't really thinking about that use case.
What about the X's in hotspot flags and the java tools command line interfaces?
The policy around command line interfaces is unchanged; the interfaces are mostly stable, but the more X's are in a flags name, the less stable it can be.
We all learned this by indoctrination from the local sensei greybeard, but where is it documented for the wider world?
There is some approximation to that guidance in the java man page; options without a "X" prefix are described as "standard" and ones with at least one "X" are described as "non-standard." Not all XX options are included in the man page.
Perhaps Supported isn't a binary thing, but needs to capture different levels of support? Solaris has had such support levels. A "beta" ("laba", "experimental") support level is very useful for introducing new technology.
It's a very hard problem, especially in a 1000 flowers world.
Yes, I'm vaguely aware that Solaris has had a rich taxonomy in this space and there are, IIRC, dtrace tools to audit if you are calling any sufficient unapproved APIs. However, at least as a first cut, I think a binary supported / not-supported distinction captures at least 80% of the distinction that needs to be made for the purposes of the JDK. Anything more involves much less favorable complexity vs benefit trade-offs. -Joe
I understand (deeply!) the problem that @Supported is trying to solve. Martin has raised a number of good questions about it already. Here are some additional concerns I'd like to see addressed before we use it any further in our source code. (I've been unable to find any earlier discussion or code review of this new annotation in the archives, but maybe I missed it.) - The annotation isn't a simple marker annotation, which is what I expected at first glance; it takes a boolean parameter. Does this mean that we have to go add "@Supported(false)" to everything that's not supported? I'd have thought that anything not marked "@Supported(true)" would by implication, well, not be supported. Does it mean that if I mark a package "@Supported(true)" I can use "@Supported(false)" on some of its member types? - Is the "supportedness" of a package inherited by its sub-packages? - The name "Supported" is problematic. It begs the question, "Supported by whom?" Maybe the annotation should take URL and phone-number parameters so that you know where to go when you run into a problem? A name that captures a more inherent property of the API unit being annotated would avoid this. Perhaps "@Stable"? - I agree with Martin that "supportedness", in the abstract, isn't a binary thing. If we're going to define an annotation for broad use then we should at least consider a metric with more than two values. I'm not saying we should replicate all the detail of the Solaris stability taxonomy [1], but we should at least discuss whether it's worth doing something along those lines, if simpler. I think it'd be particularly valuable to be able to distinguish between at least four levels: - Supported and stable (i.e., will only evolve compatibly) until we tell you it's going to go away (or change incompatibly), and we'll give you at least one feature-release cycle's notice. - Supported in this feature release, but it might go away or change incompatibly in the next, with best-effort notice. - Supported in this update release, but evolving rapidly, with changes announced only in release notes. - Internal to the JDK, expect to get burned if you use it. These are, more or less, the Solaris "Stable", "Evolving", "Unstable", and "Internal" levels, which suggests a single "@Stability" annotation and an enum parameter with the values STABLE, EVOLVING, UNSTABLE, and INTERNAL. - The retention policy of the annotation is RUNTIME. Is that really what we want? I'd have expected CLASS. - The annotation is in the top-level "jdk" package. What's the rationale for this? I'd have expected it to be defined in "jdk.annotations", so that if and when other JDK-specific annotations arise we have one convenient place to find them, and only them. Finally, this annotation is intended for use throughout our code base, and will be of interest not just to people working on the JDK but also to people using it. Its syntax, semantics, and intended usage should hence be documented in a JEP, which will be much more visible than an obscure Javadoc page. - Mark [1] http://docs.oracle.com/cd/E19082-01/819-3620/chp-stab-1/index.html
One more thought. @Supported has RUNTIME retention, and it will be inevitable that some people will check the annotation at runtime. As a practical matter, once the annotation is added, it will never be removed (or removed only if the corresponding API is itself removed), (for fear of breaking someone), including by third parties like IcedTea.
I agree, but at the same time CLASS retention is really the worst of both worlds in my opinion. It doesn't have any (convenient) runtime benefit, but you can be sure that someone will depend on it at runtime by parsing the class files (this happens surprisingly often). I'd really like to see this be SOURCE initially and only after it is well understood, move it to RUNTIME in some future version of the platform (and then make it a public API instead of a jdk specific thing). Regards, Jeroen
-----Original Message----- From: core-libs-dev-bounces@openjdk.java.net [mailto:core-libs-dev- bounces@openjdk.java.net] On Behalf Of Martin Buchholz Sent: Saturday, February 23, 2013 0:42 To: mark.reinhold@oracle.com Cc: core-libs-dev@openjdk.java.net Subject: Re: @Supported design issues
One more thought. @Supported has RUNTIME retention, and it will be inevitable that some people will check the annotation at runtime. As a practical matter, once the annotation is added, it will never be removed (or removed only if the corresponding API is itself removed), (for fear of breaking someone), including by third parties like IcedTea.
On 2/22/2013 3:04 PM, mark.reinhold@oracle.com wrote:
I understand (deeply!) the problem that @Supported is trying to solve. Martin has raised a number of good questions about it already. Here are some additional concerns I'd like to see addressed before we use it any further in our source code. (I've been unable to find any earlier discussion or code review of this new annotation in the archives, but maybe I missed it.)
- The annotation isn't a simple marker annotation, which is what I expected at first glance; it takes a boolean parameter. Does this mean that we have to go add "@Supported(false)" to everything that's not supported? I'd have thought that anything not marked "@Supported(true)" would by implication, well, not be supported. Does it mean that if I mark a package "@Supported(true)" I can use "@Supported(false)" on some of its member types?
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. We already have types in the JDK whose comments explicitly say "this is not part of any supported API" (much of javac). If there is no explicit opt-in to mark supportedness as well as non-supportedness in my estimation that means the status of all the unadorned APIs is uncertain: "Perhaps this interesting API was just overlooked in being marked supported, I'll go ahead and us it anyway..."
- Is the "supportedness" of a package inherited by its sub-packages?
No; for at least two reasons. First, annotation inheritance is only defined to work for classes along the superclass chain; there is no defined inheritance of annotations on methods or from superinterfaces. Second, subpackages of a package can have at most a tenuous logical relationship to the parent package (and they have no additional language-level access). For example, javax.annotation.processing added by JSR 269 is not really at all related to javax.annotation added by JSR 250.
- The name "Supported" is problematic. It begs the question, "Supported by whom?" Maybe the annotation should take URL and phone-number parameters so that you know where to go when you run into a problem?
I would trust that users of a JDK distribution would by default turn to the provider of their distribution for support, or barring that, stackoverflow.
A name that captures a more inherent property of the API unit being annotated would avoid this. Perhaps "@Stable"?
- I agree with Martin that "supportedness", in the abstract, isn't a binary thing. If we're going to define an annotation for broad use then we should at least consider a metric with more than two values. I'm not saying we should replicate all the detail of the Solaris stability taxonomy [1], but we should at least discuss whether it's worth doing something along those lines, if simpler. I think it'd be particularly valuable to be able to distinguish between at least four levels:
- Supported and stable (i.e., will only evolve compatibly) until we tell you it's going to go away (or change incompatibly), and we'll give you at least one feature-release cycle's notice.
- Supported in this feature release, but it might go away or change incompatibly in the next, with best-effort notice.
- Supported in this update release, but evolving rapidly, with changes announced only in release notes.
- Internal to the JDK, expect to get burned if you use it.
The status quo today and for the last 15 years has been often sloppy management of the types in com.sun.* Some of them are supported/stable/official/whatever others are not. Which are which is not clear. The closest mechanism to documenting this, aside what whatever comments might be in the code and the few subsets with published javadoc, are whether or not the types ends up in ct.sym proto-module system and if it does, whether or not a warning is issued when using the type. The ct.sym file is constructed by passing information from the docs make target to a program living in the langtools repo. So today the mechanism we have is a very an obscure system that does a poor job of conveying this kind of information and is easy to circumvent. If we go from that obscure system to an explicit boolean-valued annotation, that is in my estimation a vast improvement both in clarity and usability.
These are, more or less, the Solaris "Stable", "Evolving", "Unstable", and "Internal" levels, which suggests a single "@Stability" annotation and an enum parameter with the values STABLE, EVOLVING, UNSTABLE, and INTERNAL.
As I indicated earlier in this thread, I agree there are more subtle distinctions that can be of interest, but at times the better is the enemy of the good and the first approximation of is this type or package supported or not is a huge improvement of what we have today even if it doesn't cover all the possible gradations.
- 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.
- The annotation is in the top-level "jdk" package. What's the rationale for this? I'd have expected it to be defined in "jdk.annotations", so that if and when other JDK-specific annotations arise we have one convenient place to find them, and only them.
There are 81 subtypes of java.lang.annotation.Annotation listed in JDK 8 b77 There are four packages with "annotation" as the last component of their name in the main JDK javadoc bundle: * java.lang.annotation - types supporting the annotations language feature + 6 annotation types + 1 interface, 2 enum types, 4 throwables * javax.annotation - JSR 250's " Common Annotations for the Java Platform" + 5 annotation types + 1 enum * javax.tools.annotation - defines a single annotation used by javah functionality (probably should get a new home) + 1 annotation type * javax.xml.bind.annotation + 30 annotation types + 1 interface, 6 classes, 3 enum types That gives a total of 42 annotation types defined in packages ending with "annotation" or about half of them. However, I would discount java.lang.annotation and javax.xml.bind.annotation as outliers, in which case most JDK annotations are *not* in a dedicated package. I think it is usually not helpful to segregate annotation types into dedicated packages, after all we don't have "enums", "interfaces", and "classes" packages and there are nearly as many annotations defined directly in java.lang (SuppressWarnings, Deprecated, Override, SafeVarargs, etc.) as in java.lang.annotation. As one example, the annotation types defined in javax.annotation.processing relate directly to annotation processing and are thus in the same package as and quite at home next to the other types related to annotation processing.
Finally, this annotation is intended for use throughout our code base, and will be of interest not just to people working on the JDK but also to people using it. Its syntax, semantics, and intended usage should hence be documented in a JEP, which will be much more visible than an obscure Javadoc page.
The listed criteria for a JEP are:
It requires two or more weeks of engineering effort,
It makes a significant change to the JDK, or to the processes and infrastructure by which it is developed, or
It is in high demand by developers or customers.
Perhaps excluding this email thread, the first condition does not hold for this work and the second two conditions are debatable. In addition, this work is a direct outgrowth of the pre-modularization work going on under JEP 162: Prepare for Modularization http://openjdk.java.net/jeps/162 Given the apparent heightened interest in this topic, I trust that if a JEP for this is sent in, it will be promptly published in the JEP index. -Joe
2013/2/23 5:10 -0800, joe.darcy@oracle.com:
On 2/22/2013 3:04 PM, mark.reinhold@oracle.com wrote:
...
- The annotation isn't a simple marker annotation, which is what I expected at first glance; it takes a boolean parameter. Does this mean that we have to go add "@Supported(false)" to everything that's not supported? I'd have thought that anything not marked "@Supported(true)" would by implication, well, not be supported. Does it mean that if I mark a package "@Supported(true)" I can use "@Supported(false)" on some of its member types?
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?
We already have types in the JDK whose comments explicitly say "this is not part of any supported API" (much of javac). If there is no explicit opt-in to mark supportedness as well as non-supportedness in my estimation that means the status of all the unadorned APIs is uncertain: "Perhaps this interesting API was just overlooked in being marked supported, I'll go ahead and us it anyway..."
Okay, so that will give us a three-valued system: - @Supported(true) -- supported - @Supported(false) -- not supported - No @Supported annotation -- unknown (but probably not supported) 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. Earlier in this thread you stated "@Supported(true)" is meant to convey the same conservative evolution policy as is implicit in the SE APIs. It would be good for that policy to be captured in the specification of the annotation itself.
- Is the "supportedness" of a package inherited by its sub-packages?
No; for at least two reasons. First, annotation inheritance is only defined to work for classes along the superclass chain; there is no defined inheritance of annotations on methods or from superinterfaces. Second, subpackages of a package can have at most a tenuous logical relationship to the parent package (and they have no additional language-level access). ...
I understand both those points -- I was just wondering whether you intended to layer additional informal inheritance semantics over and above those of the language. I agree that's it's better not to do so, at least not for packages.
- The name "Supported" is problematic. It begs the question, "Supported by whom?" Maybe the annotation should take URL and phone-number parameters so that you know where to go when you run into a problem?
I would trust that users of a JDK distribution would by default turn to the provider of their distribution for support, or barring that, stackoverflow.
Let's leave this bikeshed issue for later ...
- I agree with Martin that "supportedness", in the abstract, isn't a binary thing. If we're going to define an annotation for broad use then we should at least consider a metric with more than two values. ...
The status quo today and for the last 15 years has been often sloppy management of the types in com.sun.* Some of them are supported/stable/official/whatever others are not. Which are which is not clear. The closest mechanism to documenting this, aside what whatever comments might be in the code and the few subsets with published javadoc, are whether or not the types ends up in ct.sym proto-module system and if it does, whether or not a warning is issued when using the type.
The ct.sym file is constructed by passing information from the docs make target to a program living in the langtools repo. So today the mechanism we have is a very an obscure system that does a poor job of conveying this kind of information and is easy to circumvent.
What we have today is certainly a maintenance headache for JDK developers, who have to understand the obscure makefiles involved in the construction of ct.sym. Between compile-time warnings and controlling javadoc output, however, I'd say that it does an okay job of conveying the "supportedness" of JDK-specific APIs to the rest of the world, though it could be better. 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?
If we go from that obscure system to an explicit boolean-valued annotation, that is in my estimation a vast improvement both in clarity and usability.
I agree that it's an improvement, in that it makes it easier for tools beyond javac to determine the "supportedness" of an API. I can well imagine IDEs leveraging this annotation to give advice to developers ahead of compile time. Do you plan to change the makefiles for ct.sym, and the non-SE javadoc, so that it's based on the new annotation rather than today's obscure {,NON_}CORE_PKGS.gmk files? Otherwise the maintenance headache will just get worse.
These are, more or less, the Solaris "Stable", "Evolving", "Unstable", and "Internal" levels, which suggests a single "@Stability" annotation and an enum parameter with the values STABLE, EVOLVING, UNSTABLE, and INTERNAL.
As I indicated earlier in this thread, I agree there are more subtle distinctions that can be of interest, but at times the better is the enemy of the good and the first approximation of is this type or package supported or not is a huge improvement of what we have today even if it doesn't cover all the possible gradations.
The better can be the enemy of the good, yet the expedient can be the enemy of the future. If we're going to define a new annotation with this much visibility then we should at least take the time to inventory the JDK-specific APIs that we have, and those we reasonably expect to have in the near future, to understand how many distinct levels are useful. Would it make sense, e.g., for the streams SPI in Lambda to be marked "unstable" rather than "not supported", so that javadoc for it is generated yet no commitment is made to its current form? 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.
- 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?
- The annotation is in the top-level "jdk" package. What's the rationale for this? I'd have expected it to be defined in "jdk.annotations", so that if and when other JDK-specific annotations arise we have one convenient place to find them, and only them.
There are 81 subtypes of java.lang.annotation.Annotation listed in JDK 8 b77
...
That gives a total of 42 annotation types defined in packages ending with "annotation" or about half of them. However, I would discount java.lang.annotation and javax.xml.bind.annotation as outliers, in which case most JDK annotations are *not* in a dedicated package.
I think it is usually not helpful to segregate annotation types into dedicated packages, after all we don't have "enums", "interfaces", and "classes" packages and there are nearly as many annotations defined directly in java.lang (SuppressWarnings, Deprecated, Override, SafeVarargs, etc.) as in java.lang.annotation. ...
Fair enough. What struck me as odd about "jdk.Supported" is that it's a type in a top-level package, which is not something we've ever had before. It's a bit jarring, though not illogical, so I suppose I can get used to it. 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.
Finally, this annotation is intended for use throughout our code base, and will be of interest not just to people working on the JDK but also to people using it. Its syntax, semantics, and intended usage should hence be documented in a JEP, which will be much more visible than an obscure Javadoc page.
The listed criteria for a JEP are:
It requires two or more weeks of engineering effort,
It makes a significant change to the JDK, or to the processes and infrastructure by which it is developed, or
It is in high demand by developers or customers.
Perhaps excluding this email thread, the first condition does not hold for this work and the second two conditions are debatable.
You may disagree, but I think the second condition clearly holds.
... Given the apparent heightened interest in this topic, I trust that if a JEP for this is sent in, it will be promptly published in the JEP index.
Yes, of course. - Mark
On 28/02/2013 19:31, mark.reinhold@oracle.com wrote:
:
If we're going to define a new annotation with this much visibility then we should at least take the time to inventory the JDK-specific APIs that we have, and those we reasonably expect to have in the near future, to understand how many distinct levels are useful. I didn't see any replies to this but I'm willing to do an inventory. We need this for our modularity work anyway and I think we already have a good handle on most of what is in the com.sun hierarchy. There are also a few APIs, com.apple for example, where I'm actually interesting in establishing their status as they came in without too much discussion.
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.
This is just build related as there are "supported" APIs in the langtools repository. I see Joe has added the already added the proposed annotation to com.sun.source. -Alan.
On 03/04/2013 02:28 AM, Alan Bateman wrote:
On 28/02/2013 19:31, mark.reinhold@oracle.com wrote:
:
[snip]
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.
This is just build related as there are "supported" APIs in the langtools repository. I see Joe has added the already added the proposed annotation to com.sun.source.
Just on this point for now, the jdk repo would be the more natural home for the jdk.Supported annotation, but as Alan notes, we put jdk.Supported in langtools for bootstrapping purposes since we want to use Supported in langtools as well. -Joe
On 02/28/2013 11:31 AM, mark.reinhold@oracle.com wrote:
2013/2/23 5:10 -0800, joe.darcy@oracle.com:
On 2/22/2013 3:04 PM, mark.reinhold@oracle.com wrote:
...
- The annotation isn't a simple marker annotation, which is what I expected at first glance; it takes a boolean parameter. Does this mean that we have to go add "@Supported(false)" to everything that's not supported? I'd have thought that anything not marked "@Supported(true)" would by implication, well, not be supported. Does it mean that if I mark a package "@Supported(true)" I can use "@Supported(false)" on some of its member types? 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. 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. The jdk.Supported annotation is mostly a statement to users outside of the JDK itself.
We already have types in the JDK whose comments explicitly say "this is not part of any supported API" (much of javac). If there is no explicit opt-in to mark supportedness as well as non-supportedness in my estimation that means the status of all the unadorned APIs is uncertain: "Perhaps this interesting API was just overlooked in being marked supported, I'll go ahead and us it anyway..." Okay, so that will give us a three-valued system:
- @Supported(true) -- supported - @Supported(false) -- not supported - No @Supported annotation -- unknown (but probably not supported)
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. [snip]
- I agree with Martin that "supportedness", in the abstract, isn't a binary thing. If we're going to define an annotation for broad use then we should at least consider a metric with more than two values. ... The status quo today and for the last 15 years has been often sloppy management of the types in com.sun.* Some of them are supported/stable/official/whatever others are not. Which are which is not clear. The closest mechanism to documenting this, aside what whatever comments might be in the code and the few subsets with published javadoc, are whether or not the types ends up in ct.sym proto-module system and if it does, whether or not a warning is issued when using the type.
The ct.sym file is constructed by passing information from the docs make target to a program living in the langtools repo. So today the mechanism we have is a very an obscure system that does a poor job of conveying this kind of information and is easy to circumvent. What we have today is certainly a maintenance headache for JDK developers, who have to understand the obscure makefiles involved in the construction of ct.sym.
Between compile-time warnings and controlling javadoc output, however, I'd say that it does an okay job of conveying the "supportedness" of JDK-specific APIs to the rest of the world, though it could be better.
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. 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.
If we go from that obscure system to an explicit boolean-valued annotation, that is in my estimation a vast improvement both in clarity and usability. I agree that it's an improvement, in that it makes it easier for tools beyond javac to determine the "supportedness" of an API. I can well imagine IDEs leveraging this annotation to give advice to developers ahead of compile time.
Do you plan to change the makefiles for ct.sym, and the non-SE javadoc, so that it's based on the new annotation rather than today's obscure {,NON_}CORE_PKGS.gmk files? Otherwise the maintenance headache will just get worse.
My main concern for @Supported was actually accurately capturing the classification work Alan and others have already done as part of the pre-modularization effort. However, I agree it would be preferable to change how ct.sym was generated.
These are, more or less, the Solaris "Stable", "Evolving", "Unstable", and "Internal" levels, which suggests a single "@Stability" annotation and an enum parameter with the values STABLE, EVOLVING, UNSTABLE, and INTERNAL. As I indicated earlier in this thread, I agree there are more subtle distinctions that can be of interest, but at times the better is the enemy of the good and the first approximation of is this type or package supported or not is a huge improvement of what we have today even if it doesn't cover all the possible gradations. The better can be the enemy of the good, yet the expedient can be the enemy of the future.
If we're going to define a new annotation with this much visibility then we should at least take the time to inventory the JDK-specific APIs that we have, and those we reasonably expect to have in the near future, to understand how many distinct levels are useful.
Agreed, and as indicated above, capturing the inventory that has already been done was the impetus for adding jdk.Supported at this time (I've thought about adding such a type to the JDK for several years).
Would it make sense, e.g., for the streams SPI in Lambda to be marked "unstable" rather than "not supported", so that javadoc for it is generated yet no commitment is made to its current form?
No; I think it is preferable to keep the streams types as a JDK implementation artifact to allow full de facto flexibility in designing the future SPI in that area.
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.
- The annotation is in the top-level "jdk" package. What's the rationale for this? I'd have expected it to be defined in "jdk.annotations", so that if and when other JDK-specific annotations arise we have one convenient place to find them, and only them. There are 81 subtypes of java.lang.annotation.Annotation listed in JDK 8 b77
...
That gives a total of 42 annotation types defined in packages ending with "annotation" or about half of them. However, I would discount java.lang.annotation and javax.xml.bind.annotation as outliers, in which case most JDK annotations are *not* in a dedicated package.
I think it is usually not helpful to segregate annotation types into dedicated packages, after all we don't have "enums", "interfaces", and "classes" packages and there are nearly as many annotations defined directly in java.lang (SuppressWarnings, Deprecated, Override, SafeVarargs, etc.) as in java.lang.annotation. ... Fair enough. What struck me as odd about "jdk.Supported" is that it's a type in a top-level package, which is not something we've ever had before. It's a bit jarring, though not illogical, so I suppose I can get used to it.
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 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. Cheers, -Joe
2013/3/4 2:58 -0800, joe.darcy@oracle.com:
On 02/28/2013 11:31 AM, mark.reinhold@oracle.com wrote:
2013/2/23 5:10 -0800, joe.darcy@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. - Mark
On 03/15/2013 02:12 PM, mark.reinhold@oracle.com wrote:
2013/3/4 2:58 -0800, joe.darcy@oracle.com:
On 02/28/2013 11:31 AM, mark.reinhold@oracle.com wrote:
2013/2/23 5:10 -0800, joe.darcy@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 general threshold we've been using to apply @Deprecated is that a API must be actively harmful rather than just ill-advised. However, a few methods have been deprecated in Java SE 8 because they are slated for removal in 9 as part of modularization. I would favor a shorter sequence of either @Supported(true) @Supported(false) @Deprecated <gone> or even just @Supported(true) @Supported(false) <gone> since using the API may not be harmful per se, other than risky in the sense the API is going away in the future. Using deprecation for the apt API was appropriate since that was the only documentation convention and warning-producing mechanism in place at the time. Deprecating the listener methods in pack200 in Java SE 8 is appropriate since they are Java SE API elements and not (JDK - Java SE) API elements. However, if we have a sufficiently rich supported/stable annotation, we might not need to combine usage of that annotation with @Deprecated. [snip]
...
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.
The main point I was making here is that package-info information has a less concrete existence than information about types, because, for example, it is possible to configure a build so that multiple package-info files exist for the same package (the jdk docs build gives a warning about this situation for some XML-processing code).
... 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.
It is harder to plead ignorance of the supported status of the API since any inspection of it can reveal the annotation whereas a single change in the javac command line can silence all ct.sym warnings. Cheers, -Joe
2013/3/15 17:16 -0400, joe.darcy@oracle.com:
On 03/15/2013 02:12 PM, mark.reinhold@oracle.com wrote:
...
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 general threshold we've been using to apply @Deprecated is that a API must be actively harmful rather than just ill-advised. However, a few methods have been deprecated in Java SE 8 because they are slated for removal in 9 as part of modularization.
I would favor a shorter sequence of either
@Supported(true) @Supported(false) @Deprecated <gone>
or even just
@Supported(true) @Supported(false) <gone>
since using the API may not be harmful per se, other than risky in the sense the API is going away in the future.
Agreed -- that's the key distinction: "Harmful" != "going away".
...
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.
The main point I was making here is that package-info information has a less concrete existence than information about types, because, for example, it is possible to configure a build so that multiple package-info files exist for the same package (the jdk docs build gives a warning about this situation for some XML-processing code).
Ah, yes, there's that wrinkle. I still think, though, that we should strive to give these new annotations as precise a semantics as possible, and also use them as precisely as possible.
...
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.
It is harder to plead ignorance of the supported status of the API since any inspection of it can reveal the annotation whereas a single change in the javac command line can silence all ct.sym warnings.
Okay. I took the word "cirvumvent" to mean that you had some additional automatic enforcement mechanism in mind. - Mark
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. Just a personal opinion as a developer. Java APIs are very big and removing deprecated APIs can reduce this size. It will help solving this question: "what can be the name of the currently needed class/method in all these APIs?", which is very important, particularly for new Java developers, frequently lost in these numerous APIs.
Readability is the biggest design feature of Java, then I think there is some logic if developers ask for removal of deprecated API, because it will improve readability of APIs.
1. I suspect that the percentage of deprecated APIs is less than 0.1 % .. So removing 1 ouf every 1,000 methods is not exactly going to make a huge difference here. 2. Some methods were deprecated at a time when the policy was to encourage people to use "newer" API, even though there wasn't anything very wrong. with the old one. For example Component.show()/hide() were deprecated in favour of Component.setVisible(boolean) although as far as I know there's absolutely no problem with the former. So such a policy would not be something you could apply automatically you'd need to go examine each case to understand it. 3. Removing methods *from the doc* and *from the runtime* each have their consequences, from the doc would discourage new uses but make it harder to understand old code. I think a long ago ill-fated JSR for javadoc improvements pondered hiding deprecated methods if you didn't want to see them. Remiving from the runtime would break apps, and in some cases people don't have the option to change and fix. -phil. On 3/16/13 2:10 PM, Daniel Latrémolière wrote:
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. Just a personal opinion as a developer. Java APIs are very big and removing deprecated APIs can reduce this size. It will help solving this question: "what can be the name of the currently needed class/method in all these APIs?", which is very important, particularly for new Java developers, frequently lost in these numerous APIs.
Readability is the biggest design feature of Java, then I think there is some logic if developers ask for removal of deprecated API, because it will improve readability of APIs.
1. I suspect that the percentage of deprecated APIs is less than 0.1 % .. So removing 1 ouf every 1,000 methods is not exactly going to make a huge difference here.
2. Some methods were deprecated at a time when the policy was to encourage people to use "newer" API, even though there wasn't anything very wrong. with the old one. For example Component.show()/hide() were deprecated in favour of Component.setVisible(boolean) although as far as I know there's absolutely no problem with the former. So such a policy would not be something you could apply automatically you'd need to go examine each case to understand it. Yes or no for 0,1%, depending if you include some big parts like AWT, Swing, CORBA which are obsolete for many developers, because they are not considered up-to-date for their domains (UI, RPC) and their development is stopped. In this case, deprecated or obsolete API are concerning important domains, like:
* UI (AWT -> Swing -> JavaFX), * date management (Date -> Calendar -> JSR 310) * RPC (RMI, CORBA, WebServices, REST like JAX-RS: not all are used even if winner depends of project). * LDAP dedicated API are provided by vendors like Apache Directory, OpenDJ for replacing JNDI (not evolving since Java 1.4 and seen not sufficiently specialized). * Logging API is split between java.util.logging, Log4J, SLF4J (depending of project). Other domains has evolved (like IO, NIO, NIO2) but contains some complex differences: e.g. Path vs. File. Considering File as deprecated in Java7 is frequent even if it is not official: http://stackoverflow.com/questions/6903335/java-7-path-vs-file Another related problem for a developer is that many parts of API show their age given others enhancements: e.g. Math/StrictMath classes were introduced before Integer/Long/Float/Double classes but would probably not have existed if order was inverse (static methods are notoriously difficult to find, because we don't know by default the class containing them). Globally, an API designed before Java 1.5 has usually be updated for generics but not for enumerations and only partially for annotations. Now, seeing an int for describing an enumeration in an API became surprising (like Modifier in reflection). Marker interfaces (like java.io.Serializable, java.util.RandomAccess) have same problem against annotations. The reason is simply that Java 1.5 is old: it has 8.5 years. API designed before have accumulated a technical debt and are not seen up-to-date. I think, I have covered big parts of Java API, concerning all developers, with various names (deprecated, obsolete, technical debt) for only one problem: feeling of an old API and need of cleaning it. NB: With static methods in interface, you will probably have the same problem in some years: 1) First round: add factories methods in interface. Developer speaking: When I want an instance of an interface it is always difficult to search a subclass and only after that call its constructor. I want to go to the expected interface and call a static factory for all my frequent usecases, then: please add some static methods like followings in List class (and all other interfaces with implementations provided by default): public static <E> List<E> newRandomAccessList() { return new ArrayList<E>(); } public static <E> List<E> newLinearAccessList() { return new LinkedList<E>(); } 2) Second round (some years after): remove them from public API. Developer speaking: I do not need to see AbstractList, ArrayList and LinkedList because I don't call them directly, at least in 99% of my usecases. This is a List-related implementation detail only useful when I want to create my own custom List for a highly specific and performance-sensitive usecase. Remove these classes from public API and put them in another library not seen by me by default, excepted if I really search it. In Javadoc, I only see the signature of method, and not the code of method (implementation detail), then I don't want to see these classes only implementing interfaces (implementation detail): the factory method in interface is sufficient with one paragraph in the Javadoc giving tradeoffs of each implementation provided by default.
3. Removing methods *from the doc* and *from the runtime* each have their consequences, from the doc would discourage new uses but make it harder to understand old code. I think a long ago ill-fated JSR for javadoc improvements pondered hiding deprecated methods if you didn't want to see them. Remiving from the runtime would break apps, and in some cases people don't have the option to change and fix. Currently, profiles are clearly reducing some API complexity for developer. NB: JavaFX doclet seems to remove methods with prefix impl_ from Javadoc.
I think it seems sad, that one of the biggest differences between Java and shorter language like JavaScript is static typing: it give an excellent accuracy when used for automatic refactoring in Java. Given static typing, IDE have added many automatic refactoring and some mechanisms for helping updating code (e.g. generics), JSR 308 has also some inference tools. But bytecode refactoring (AOT in build process or JIT in ClassLoader) was mostly used for supporting new Java code with old JVM (Retroweaver, Retrotranslator) and not the inverse: supporting old Java bytecode on new JVM. I thought it was possibly used for executing JavaME program on JavaSE JVM but I am not sure. <utopia> I hope of a future where Java easier refactoring (given static typing) would help evolving Java faster by breaking direct compatibility while keeping sufficiently real compatibility (old programs are only slightly slower in compatibility ClassLoader). With easier evolution, Java API can be better organized and developer become happy. </utopia> NB: I never used "Java platform" because I think Java is slowly evolving, for developers, to become more a library for their application, than a platform containing application. Having an integrated JVM in each application is a big change in compatibility requirements, because developer has control on compatibility and it will possibly relax some constraints. 1) JavaEE applications are evolving to include server and not inverse: http://www.adam-bien.com/roller/abien/entry/why_not_one_application_per 2) JavaSE applications are evolving to include JVM and not to run on a JVM provided by OS: mobile OS prohibiting shared libraries and security problems of OS-global JVM define the rules: http://fxexperience.com/2012/06/application-deployment-with-javafx/
That isn't at all what @deprecated means. "Encouraged for new development" doesn't mean everything else is @deprecated. These are all part of the Java SE platform spec, and are documented as such and are fully supported .. a focus on compatibility is very important to a lot of our customers, even if that's not you. -phil. On 3/17/13 12:10 PM, Daniel Latrémolière wrote:
1. I suspect that the percentage of deprecated APIs is less than 0.1 % .. So removing 1 ouf every 1,000 methods is not exactly going to make a huge difference here.
2. Some methods were deprecated at a time when the policy was to encourage people to use "newer" API, even though there wasn't anything very wrong. with the old one. For example Component.show()/hide() were deprecated in favour of Component.setVisible(boolean) although as far as I know there's absolutely no problem with the former. So such a policy would not be something you could apply automatically you'd need to go examine each case to understand it. Yes or no for 0,1%, depending if you include some big parts like AWT, Swing, CORBA which are obsolete for many developers, because they are not considered up-to-date for their domains (UI, RPC) and their development is stopped. In this case, deprecated or obsolete API are concerning important domains, like:
* UI (AWT -> Swing -> JavaFX), * date management (Date -> Calendar -> JSR 310) * RPC (RMI, CORBA, WebServices, REST like JAX-RS: not all are used even if winner depends of project). * LDAP dedicated API are provided by vendors like Apache Directory, OpenDJ for replacing JNDI (not evolving since Java 1.4 and seen not sufficiently specialized). * Logging API is split between java.util.logging, Log4J, SLF4J (depending of project).
Other domains has evolved (like IO, NIO, NIO2) but contains some complex differences: e.g. Path vs. File. Considering File as deprecated in Java7 is frequent even if it is not official: http://stackoverflow.com/questions/6903335/java-7-path-vs-file
Another related problem for a developer is that many parts of API show their age given others enhancements: e.g. Math/StrictMath classes were introduced before Integer/Long/Float/Double classes but would probably not have existed if order was inverse (static methods are notoriously difficult to find, because we don't know by default the class containing them).
Globally, an API designed before Java 1.5 has usually be updated for generics but not for enumerations and only partially for annotations. Now, seeing an int for describing an enumeration in an API became surprising (like Modifier in reflection). Marker interfaces (like java.io.Serializable, java.util.RandomAccess) have same problem against annotations. The reason is simply that Java 1.5 is old: it has 8.5 years. API designed before have accumulated a technical debt and are not seen up-to-date.
I think, I have covered big parts of Java API, concerning all developers, with various names (deprecated, obsolete, technical debt) for only one problem: feeling of an old API and need of cleaning it.
NB: With static methods in interface, you will probably have the same problem in some years:
1) First round: add factories methods in interface. Developer speaking: When I want an instance of an interface it is always difficult to search a subclass and only after that call its constructor. I want to go to the expected interface and call a static factory for all my frequent usecases, then: please add some static methods like followings in List class (and all other interfaces with implementations provided by default): public static <E> List<E> newRandomAccessList() { return new ArrayList<E>(); } public static <E> List<E> newLinearAccessList() { return new LinkedList<E>(); }
2) Second round (some years after): remove them from public API. Developer speaking: I do not need to see AbstractList, ArrayList and LinkedList because I don't call them directly, at least in 99% of my usecases. This is a List-related implementation detail only useful when I want to create my own custom List for a highly specific and performance-sensitive usecase. Remove these classes from public API and put them in another library not seen by me by default, excepted if I really search it. In Javadoc, I only see the signature of method, and not the code of method (implementation detail), then I don't want to see these classes only implementing interfaces (implementation detail): the factory method in interface is sufficient with one paragraph in the Javadoc giving tradeoffs of each implementation provided by default.
3. Removing methods *from the doc* and *from the runtime* each have their consequences, from the doc would discourage new uses but make it harder to understand old code. I think a long ago ill-fated JSR for javadoc improvements pondered hiding deprecated methods if you didn't want to see them. Remiving from the runtime would break apps, and in some cases people don't have the option to change and fix. Currently, profiles are clearly reducing some API complexity for developer. NB: JavaFX doclet seems to remove methods with prefix impl_ from Javadoc.
I think it seems sad, that one of the biggest differences between Java and shorter language like JavaScript is static typing: it give an excellent accuracy when used for automatic refactoring in Java. Given static typing, IDE have added many automatic refactoring and some mechanisms for helping updating code (e.g. generics), JSR 308 has also some inference tools.
But bytecode refactoring (AOT in build process or JIT in ClassLoader) was mostly used for supporting new Java code with old JVM (Retroweaver, Retrotranslator) and not the inverse: supporting old Java bytecode on new JVM. I thought it was possibly used for executing JavaME program on JavaSE JVM but I am not sure.
<utopia> I hope of a future where Java easier refactoring (given static typing) would help evolving Java faster by breaking direct compatibility while keeping sufficiently real compatibility (old programs are only slightly slower in compatibility ClassLoader). With easier evolution, Java API can be better organized and developer become happy. </utopia>
NB: I never used "Java platform" because I think Java is slowly evolving, for developers, to become more a library for their application, than a platform containing application. Having an integrated JVM in each application is a big change in compatibility requirements, because developer has control on compatibility and it will possibly relax some constraints. 1) JavaEE applications are evolving to include server and not inverse: http://www.adam-bien.com/roller/abien/entry/why_not_one_application_per 2) JavaSE applications are evolving to include JVM and not to run on a JVM provided by OS: mobile OS prohibiting shared libraries and security problems of OS-global JVM define the rules: http://fxexperience.com/2012/06/application-deployment-with-javafx/
That isn't at all what @deprecated means.
"Encouraged for new development" doesn't mean everything else is @deprecated. These are all part of the Java SE platform spec, and are documented as such and are fully supported .. a focus on compatibility is very important to a lot of our customers, even if that's not you. Sorry if I have not clearly read, but it is not my opinion on Swing.
Just for explaining reasons of my opinion (if you found some others people thinking like me) and not really arguing (person-specific then usually near useless), I will give you some texts inducing this personal point of view on Swing. --- When to Deprecate When you design an API, carefully consider whether it supersedes an old API. If it does, and you wish to encourage developers (users of the API) to migrate to the new API, then deprecate the old API. http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/deprecation/de... --- 6. Is JavaFX replacing Swing as the new client UI library for Java SE? Yes. However, Swing will remain part of the Java SE specification for the foreseeable future, and therefore included in the JRE. While we recommend developers to leverage JavaFX APIs as much as possible when building new applications, it is possible to extend a Swing application with JavaFX, allowing for a smoother transition. http://www.oracle.com/technetwork/java/javafx/overview/faq-1446554.html#6 --- [JEP 161] The primary motivation for this feature is to allow applications that do not require the entire Java SE Platform to run on resource-constrained devices. An application that does not use the Swing/AWT/2D graphics stack, e.g., or which uses Java FX instead, can achieve considerable space savings by running on top of a Profile that does not include those APIs. [... CDC migration to JavaSE ...] As a secondary benefit, this feature is likely to enable faster download times for applications that bundle their own Java Runtime Environment (JRE). http://openjdk.java.net/jeps/161 --- JavaFX applications have implicit dependency on the availability of Java and JavaFX runtimes, and while existing deployment methods provide a means to validate the system requirements are met -- and even guide the user to perform required installation/upgrades -- they do not fully address all of the important scenarios. In particular, here are few examples: the user may not have admin permissions to install new system software if the application was certified to run in the specific environment (fixed version of Java and JavaFX) then it may be hard to ensure user has this environment due to an autoupdate of the system version of Java/JavaFX (to ensure they are secure). Potentially, other apps may have a requirement for a different JRE or FX version that your app is incompatible with. your distribution channel may disallow dependencies on external frameworks (e.g. Mac AppStore) https://blogs.oracle.com/talkingjavadeployment/entry/native_packaging_for_ja...
FYI, I've submitted a JEP reviewed by Alan Bateman on "Capturing support and stability information about JDK classes in source and class files." -Joe
On 3/14/2013 10:14 AM, Joe Darcy wrote:
FYI, I've submitted a JEP reviewed by Alan Bateman on "Capturing support and stability information about JDK classes in source and class files."
Following up in the same thread, the JEP for this work is now available for your reading pleasure at: JEP 179: Document JDK API Support and Stability http://openjdk.java.net/jeps/179 -Joe
On 20/03/2013 01:32, Joseph Darcy wrote:
Following up in the same thread, the JEP for this work is now available for your reading pleasure at:
JEP 179: Document JDK API Support and Stability http://openjdk.java.net/jeps/179
Joe - do you want to reboot this discussion? With the deadline for API changes looming then it would be good to get agreement on whether we are going to do anything on this. I still have the patch to add this to the APIs that we generate javadoc for in the build - this is the same set of APIs that I understand to be stable APIs and okay for applications/libraries to make direct use of. Given the previous discussion then getting agreement on whether this is a boolean or something more seems important. Clearly there are corner cases (a few of these came up in the original discussion) but a simple label to convey that an API is stable seems a good start. The other problematic issue was the naming, clearly "Supported" results in too many questions, "by who?" in particular. Have you considered alternative names? I realize this is open to bikeshedding. Personally I wouldn't have a problem with jdk.Stable if appropriately defined. -Alan
On 9/5/2013 2:20 AM, Alan Bateman wrote:
On 20/03/2013 01:32, Joseph Darcy wrote:
Following up in the same thread, the JEP for this work is now available for your reading pleasure at:
JEP 179: Document JDK API Support and Stability http://openjdk.java.net/jeps/179
Joe - do you want to reboot this discussion? With the deadline for API changes looming then it would be good to get agreement on whether we are going to do anything on this. I still have the patch to add this to the APIs that we generate javadoc for in the build - this is the same set of APIs that I understand to be stable APIs and okay for applications/libraries to make direct use of.
Given the previous discussion then getting agreement on whether this is a boolean or something more seems important. Clearly there are corner cases (a few of these came up in the original discussion) but a simple label to convey that an API is stable seems a good start. The other problematic issue was the naming, clearly "Supported" results in too many questions, "by who?" in particular. Have you considered alternative names? I realize this is open to bikeshedding. Personally I wouldn't have a problem with jdk.Stable if appropriately defined.
IMO, the high order goal here should be getting the "is this API okay to use" information encoded into the source code and class files. Given that you've already compiled that information, I think there is great value in going forward with this effort for JDK 8 even given the relatively late point in the schedule. Perhaps instead of "Supported", the adjective "Sanctioned" better conveys what is intended: this API is explicitly part of the JDK's contract and fine to use. I'm open to other suggestions too. Cheers, -Joe
2013/9/5 12:33 -0700, joe.darcy@oracle.com:
IMO, the high order goal here should be getting the "is this API okay to use" information encoded into the source code and class files. Given that you've already compiled that information, I think there is great value in going forward with this effort for JDK 8 even given the relatively late point in the schedule.
Agreed.
Perhaps instead of "Supported", the adjective "Sanctioned" better conveys what is intended: this API is explicitly part of the JDK's contract and fine to use.
@Sanctioned begs the same question as @Supported, i.e., by whom?
I'm open to other suggestions too.
Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology. Just one idea, I'm sure there are others. - Mark
On 9/5/2013 8:23 PM, mark.reinhold@oracle.com wrote:
2013/9/5 12:33 -0700, joe.darcy@oracle.com:
IMO, the high order goal here should be getting the "is this API okay to use" information encoded into the source code and class files. Given that you've already compiled that information, I think there is great value in going forward with this effort for JDK 8 even given the relatively late point in the schedule. Agreed.
Perhaps instead of "Supported", the adjective "Sanctioned" better conveys what is intended: this API is explicitly part of the JDK's contract and fine to use. @Sanctioned begs the same question as @Supported, i.e., by whom?
I don't think the answers here are that vexing; in analogy with @Deprecated, the party providing the type is the party providing information about the intended use of that type.
I'm open to other suggestions too. Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
Just one idea, I'm sure there are others.
Thanks for the suggestion, -Joe
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going. Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8. -Alan.
On 9/10/2013 6:28 AM, Alan Bateman wrote:
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going.
Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8.
I don't object to using @Exported. Cheers, -Joe
On 9/10/13 9:47 AM, Joe Darcy wrote:
On 9/10/2013 6:28 AM, Alan Bateman wrote:
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going.
Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8.
I don't object to using @Exported.
I like @Exported as well. Mandy
On 09/10/2013 11:54 AM, Mandy Chung wrote:
On 9/10/13 9:47 AM, Joe Darcy wrote:
On 9/10/2013 6:28 AM, Alan Bateman wrote:
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going.
Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8.
I don't object to using @Exported.
I like @Exported as well.
If we're framing it in terms of modules, I think it would make more sense to have exporting be default and "hidden" be opt-in. And, while we're at it, "hidden" really ought to apply at a package level, not a class level. In other words: don't make this about modularity. -- - DML
On 9/10/2013 10:08 AM, David M. Lloyd wrote:
On 09/10/2013 11:54 AM, Mandy Chung wrote:
On 9/10/13 9:47 AM, Joe Darcy wrote:
On 9/10/2013 6:28 AM, Alan Bateman wrote:
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going.
Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8.
I don't object to using @Exported.
I like @Exported as well.
If we're framing it in terms of modules, I think it would make more sense to have exporting be default and "hidden" be opt-in.
And, while we're at it, "hidden" really ought to apply at a package level, not a class level.
In other words: don't make this about modularity.
To bring in some of the initial context, this feature is about documenting and formalizing the historically unclear exported-ness/supported-ness of types in the com.sun.* packages. Some com.sun.* types are intended to be used outside of the JDK while others are not. To bring clarity to this situation, I'd like to see each type and package in com.sun.* either have an explicit @Exported(true) XOR @Exported(false) annotation applied to it. This make a clear statement around the intentions of the type and will allow better tooling to be written. -Joe
On 09/10/2013 06:26 PM, Joseph Darcy wrote:
On 9/10/2013 10:08 AM, David M. Lloyd wrote:
On 09/10/2013 11:54 AM, Mandy Chung wrote:
On 9/10/13 9:47 AM, Joe Darcy wrote:
On 9/10/2013 6:28 AM, Alan Bateman wrote:
On 06/09/2013 04:23, mark.reinhold@oracle.com wrote:
: Well, looking ahead to when the platform will be composed of modules, those modules will declare that they "export" some API elements, but not others. An @Exported annotation would help get people used to the expected future terminology.
@Exported is quite good, and consistent with where this is likely going.
Joe - what would you think of just running with this? I'm anxious that we decide on this soon so that we don't run out of time in jdk8.
I don't object to using @Exported.
I like @Exported as well.
If we're framing it in terms of modules, I think it would make more sense to have exporting be default and "hidden" be opt-in.
And, while we're at it, "hidden" really ought to apply at a package level, not a class level.
In other words: don't make this about modularity.
To bring in some of the initial context, this feature is about documenting and formalizing the historically unclear exported-ness/supported-ness of types in the com.sun.* packages. Some com.sun.* types are intended to be used outside of the JDK while others are not.
I'm aware of that; however I guarantee you that if you try to munge this functionality up with the concept of exported classes or packages before the module system is realized, it's going to end up wrong and we'll have yet more dead cruft in the API.
To bring clarity to this situation, I'd like to see each type and package in com.sun.* either have an explicit @Exported(true) XOR @Exported(false) annotation applied to it. This make a clear statement around the intentions of the type and will allow better tooling to be written.
"Plus one" for this, modulo a request to not use the term "Exported" and/or not make this annotation part of the public API. -- - DML
On 11/09/2013 03:50, David M. Lloyd wrote:
I'm aware of that; however I guarantee you that if you try to munge this functionality up with the concept of exported classes or packages before the module system is realized, it's going to end up wrong and we'll have yet more dead cruft in the API.
There isn't any real functionality here, it's simply an effort to make it clear which com.sun.** APIs are okay for developers to depend on. This is useful for JDK maintainers too. If/when we move to a modular JDK then it would be reasonable to expect that the @Exported APIs would be APIs that applications can continue to depend on. It may be that some of the non-@Exported JDK-specific APIs are completely hidden from applications, in which case having @Exported now is a good thing as it helps developers and tooling be aware that they may be directly using JDK internal APIs, perhaps unknowingly. We also include rudimentary tooling (jdeps) to help in the effort to understand dependencies. It may be that jdeps should be extended to also look at the @Exported annotation. As I mention non-@Exported APIs then I don't think (and Joe can confirm) that there is any intention to add @Exported(false) to thousands of JDK-internal classes (and their package-info.java if it exists). Rather, if @Exported is not present then the default answer has to be that it is ambiguous and so not safe to depend on. Assuming I have this right then it means that @jdk.Exported (or whatever the final name is) will only be added to the small number of JDK-specific APIs that are long term stable/supported/documented APIs. This is consistent with the patches that have been discussed to date [1][2]. -Alan [1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/011cf7e0a148 [2] http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-February/014691.ht...
Thank you Alan, this will clear up a lot of issues surrounding these API's. I skimmed over the changes, paying particular attention to the httpserver and sctp packages. -Chris. On 02/21/2013 06:46 PM, Alan Bateman wrote:
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs.
I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported". Specifically I'm proposing to add it to:
- Java Debug Interface (com.sun.jdi) - Attach API (com.sun.tools.attach) - SCTP API (com.sun.nio.sctp) - HTTP server API (com.sun.net.httpserver) - Management extensions (com.sun.management) - JDK-specific API to JAAS (com.sun.security.auth) - JDK-specific JGSS API (com.sun.security.jgss)
The javadoc for all of these is generated as part of the regular JDK "docs" build and so shouldn't be controversial. There are a number of other candidates in com.sun with murkier status that I've stayed clear of for now.
The webrev with the changes is here:
http://cr.openjdk.java.net/~alanb/8008662/webrev/
In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java.
In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that.
Otherwise this is mostly mechanical and the patch file is easier to review that the webrev.
-Alan
[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
The security related ones look ok to me. --Sean On 02/21/2013 01:46 PM, Alan Bateman wrote:
Joe Darcy recently added @jdk.Supported [1] to make it possible to identify JDK-specific APIs.
I'd like to add this to a number of APIs in the com.sun namespace to make it obvious these are "supported". Specifically I'm proposing to add it to:
- Java Debug Interface (com.sun.jdi) - Attach API (com.sun.tools.attach) - SCTP API (com.sun.nio.sctp) - HTTP server API (com.sun.net.httpserver) - Management extensions (com.sun.management) - JDK-specific API to JAAS (com.sun.security.auth) - JDK-specific JGSS API (com.sun.security.jgss)
The javadoc for all of these is generated as part of the regular JDK "docs" build and so shouldn't be controversial. There are a number of other candidates in com.sun with murkier status that I've stayed clear of for now.
The webrev with the changes is here:
http://cr.openjdk.java.net/~alanb/8008662/webrev/
In a couple of cases the package description is legacy package.html so I've had to move/convert them to package-info.java.
In all but one case I've added the annotation to the package-info, the one exception is com.sun.management where there is at least one type that is documented as "not supported". Joe Darcy might have suggestions on that.
Otherwise this is mostly mechanical and the patch file is easier to review that the webrev.
-Alan
[1] http://hg.openjdk.java.net/jdk8/tl/langtools/rev/55cca2f38ee6
participants (13)
-
Alan Bateman
-
Chris Hegarty
-
Daniel Latrémolière
-
David M. Lloyd
-
Jeroen Frijters
-
Joe Darcy
-
Joseph Darcy
-
Lance Andersen - Oracle
-
Mandy Chung
-
mark.reinhold@oracle.com
-
Martin Buchholz
-
Phil Race
-
Sean Mullan