Thanks for that response, Stuart. One comment inline...
On 5/31/16 5:34 PM, Stuart Marks wrote:
On 5/30/16 11:48 AM, Richard Hillegas wrote:
Dalibor Topic recommended that I post this feedback on core-libs-dev.
This is my
feedback after ameliorating the deprecation warnings which surfaced
when I
compiled and tested Apache Derby with early access builds 116 and 118
of JDK 9.
Derby is a pure Java relational database whose original code goes
back almost 20
years. Other large, old code bases (like Weblogic) may have similar
experiences.
More detail on my experience can be found on the JIRA issue which
tracks the
Derby community's attempt to keep our code evergreen against JDK 9:
https://issues.apache.org/jira/browse/DERBY-6856
Hi Rick,
Thanks for your feedback on the API deprecations.
A couple notes on deprecation. First, the deprecation JEP (JEP 277)
[1] has clarified the definition of deprecation so that by default it
no longer means that the API will be removed. In the absence of
forRemoval=true, deprecation is merely a recommendation for code to
migrate away from the annotated API. Only when the forRemoval=true
element is present does it mean that the API is actually going to be
removed. None of these deprecations has forRemoval=true, this means
that there's no great urgency for anyone to migrate away from them.
Now, they will generate compilation warnings, which is quite possibly
a problem. There are some existing mechanisms for disabling warnings,
such as -Xlint:-deprecation and the @SuppressWarnings annotation.
These might not be sufficient. We're considering adding some
finer-grained mechanisms. Ideally, for deprecated APIs that aren't
being removed, it should be possible to manage the warnings so that
migration of any code base can proceed at whatever pace its
maintainers feel is appropriate, without it being forced by any
particular JDK release.
This was the issue which I faced. The Derby community has spent
considerable effort on maintaining a clean build, one which doesn't
swamp real error indications in a blizzard of diagnostic noise. At the
same time, we are reluctant to wholesale-disable all deprecation
warnings because, in general, they do provide useful advice about best
practices. The ameliorations you are considering do sound useful. I
don't have any better suggestions at this time.
Thanks,
-Rick
If you have any thoughts on how to better manage deprecation warnings,
I'd love to hear them.
o Deprecating autoboxing constructors - Deprecating the autoboxing
constructors
for primitive wrapper objects caused a large rototill of Derby code.
That
rototill was comparable in size to the changes made necessary by Java
5's
introduction of generics. Hopefully, IDEs can automate much of this
chore.
The boxing constructors -- e.g., new Integer(432) -- are the ones
being deprecated. The preferred alternative is Integer.valueOf(432).
Note that *auto*boxing ends calling valueOf() under the covers.
Autoboxing is generally preferable, although not without pitfalls,
such as the overloading of List.remove(int) vs List.remove(Object), as
you stumbled across in the referenced bug report. Using valueOf()
instead of autoboxing would have avoided the error.
o Deprecating Class.newInstance() - The deprecation of
Class.newInstance()
forced a similarly large rototill. The code became more verbose.
Additional
exceptions had to be caught and propagated up the call stack. For
reasons which
I don't understand, I had better luck using
Class.getConstructor().newInstance()
than Class.getDeclaredConstructor().newInstance(). But the former
replacement
code requires you to make constructors public. For some code bases,
that may
introduce security problems which are worse than the security problem
being
addressed by this deprecation. I hope that IDEs and the release notes
for JDK 9
will provide some guidance for how to handle these issues.
It would be good to understand why getDeclaredConstructor() didn't
work. Clearly requiring a public no-arg constructor is a non-starter.
o Deprecating java.util.Observable and java.util.Observer - Two
ameliorations
are recommended at
http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-April/040436.html.
The
first suggestion (use the awt event model) runs very much counter to
the whole
intent of Jigsaw. That is because pulling in awt can bloat up an
application
with large, otherwise unneeded libraries. Using awt was out of the
question for
Derby, given that the community had already invested a great deal of
effort in
paring back Derby's dependencies in order to let the code run on JDK
8 compact
profile 2. That left us with the other option: write your own
replacement
classes. If a lot of people end up having to write the same
replacement code,
then that argues for leaving this small but useful functionality in
the JDK. I
think that the people who advocated for this deprecation did not have
good
visibility into how widely these classes are being used in the wild.
I recommend
that this deprecation be re-evaluated.
Observable and Observer have a long history of problem reports and
enhancement requests that show that people want them to be something
other than what they are. This includes: Observable should be an
interface, not an abstract class; there is only one "changed" bit,
without any notion of what has changed; there is no control over what
thread calls observers; there is no ability to control sequence of
calls to observers; change notifications aren't in one-for-one
correspondence with change updates; Observers are compared using
equals() not reference equality; and so forth.
The point of deprecating Observable/Observer is to tell people looking
for some event notification mechanism to avoid using this one, as it
seems quite likely that it won't satisfy their needs. It also tells
current users that if they're running into its shortcomings, they
probably won't be addressed. The suggestion of using java.beans
properties as an alternative is there because the beans notification
model was developed to address many of the shortcomings of
Observable/Observer.
Of course beans doesn't work for everything. If Observable/Observer
does exactly what Derby needs, then Derby can continue to use it
indefinitely. There's no need to remove it.
s'marks