This post originated from an RSS feed registered with Java Buzz
by Tim Vernum.
Original Post: Java Backwards Compatability
Feed Title: A word used to describe something
Feed URL: http://blog.adjective.org/feed/category/Development/rss2
Feed Description: Tim's random musings on software development, java, jetty and other such frivolities.
Ted blogged about the absence of
leadership in the direction of Java (the language).
One of the comments there suggested we forget about backward
compatibility.
I'm not necessarily for or against that idea, but I do think it's worth
thinking about, so we know what it is we're trying to preserve, and what we're
willing to give up.
By necessity then, the first step must be to define what we mean be
backwards compatibility...
Ted blogged about the absence of
leadership in the direction of Java (the language).
One of the comments there suggested we forget about backward
compatibility.
I'm not necessarily for or against that idea, but I do think it's worth
thinking about, so we know what it is we're trying to preserve, and what we're
willing to give up.
By necessity then, the first step must be to define what we mean be
backwards compatibility. There are a number of possible ways we can be
"backwards compatible" and some of them are easier to manage than others.
Since the original post/comment was about Java 7, I'm going to use "Java 6"
to mean the "old" version of Java that we're trying to stay compatible with and
"Java 7" to refer to the new, perhaps incompatible version. And I'll use
closures as an example of a feature in Java 7 that may interfere with
compatibility. You can substitute in your own features and version numbers if
you wish.
As best I can identify, the various ways to preserve backwards compatibility
are:
At the binary level
1. Source written in Java 6 can be recompiled for Java 7
For some people, this may be enough. Ditch any plans to keep running existing
class files, throw away your binary jar files (or run them through a Java 7
converter), and recompile everything from source. It's more or less what
Android is (although it hasn't added a new alternate syntax). However, it means
that the new VM can't run old applets (for the devoted few who still care about
applets) and it also means that you can't download a jar file from the internet
and use it in your app unless you know whether it's a Java 6 jar file, or a
Java 7 jar file. In practice we already have that problem. Java 5 jar files
don't run on a Java 4 VM. But this would create the reverse - Java 6 jar files
won't run on Java 7 VMs and Java 7 jar files won't run on Java 6 VMs. The only
extent to which this can be considered to be "backwards compatible" is that you
don't have to throw away your existing source code. You can make it run on the
new VM (with a small amount of effort)
2. Old applications run unchanged on new VMs At its
simplest, that just means that the Java 7 VM has support for running a pure
Java 6 application. It's a bit like the Playstation 2 being compatible with the
original Playstation - it had a PS1 embedded in it so it could play PS1 games.
However, since JEE deployments are a significant focus on the java landscape,
we probably need to extend the definition of an application to include anything
packaged as an EAR or WAR file. Which means we need app servers that can run
Java 6 applications as well as Java 7 applications. Presumably at the same
time. The main complexity in that is the consequences for rt.jar.
Does the VM need to expose a single version of rt.jar that is
compatible with both Java 6 and Java 7 applications? Would it be possible for
an app server running on a Java 7 VM to provide different versions of
rt.jar to the different applications? Or would we need to have an
rt.jar with a java.util package and a
java7.util package? (The latter of which has serious consequences
for the other possible definitions of "backwards compatible")
3. Old class files can be used by new class files (written in Java
7) This would mean that your new Java 7 source code would be able to
use the existing jar file for your JDBC driver. It means that as far as Java 7
is concerned we need
A VM that can run Java 6 class files alongside Java 7 class files
A calling method from a Java 7 class file to a method in a Java 6 class
file
4. Old class files can call methods on Java 7 classes If
you want to be able to write a ListModel in Java 7, and then pass
that to a swing component written in Java 6, then you need this. To do it
properly, it means that the Java 6 code can use reflection on the Java 7 class,
and get meaningful data back. The class file format may not need to be anything
like the Java 6 class file format, but the reflection APIs and classloaders
need to be able to hide the differences. This form of compatibility was one of
the requirements that impacted generics.
At the source level
5. The Java 7 version of "javac" knows how to compile both Java 6
and Java 7 code This is easy. The Groovy compiler already does this -
you just need a way to work out which syntax is being used in a source
file.
6. Source that uses the Java 7 syntax can call methods on Java 6
classes This is pretty simple to do. The new syntax needs a way to
invoke a Java 6 method, but the various "new" syntaxes being played with
(Groovy, Scala, etc) already support this (although as Gilad Bracha's recent post on
static variables points out, it has constrained the design of those
languages).
7. Source that uses the old Java 6 syntax can call methods on new
Java 7 classes This is fairly straight forward if you're happy to
require that it's compiled with the new compiler. You need to decide what to do
about classes that use new features. E.g. What if Java 6 code calls a method
that returns a closure? If the Java 6 syntax has no way to represent that
closure, then we have a problem.
8. Source written in Java 6 can have Java 7 features added to it
slowly This would require that every Java 6 source file is also a
valid Java 7 source file. It means that I can have a single source file,
defining a single class, and one of the methods (that was written years ago)
uses the old Java 6 syntax, while another method (that I wrote today) uses the
new Java 7 syntax. And they live happily together in the same file.
I think we're likely to find different people care about different
definitions for "backwards compatibility", and there will be some people who
think we need to support all of them.
My personal opinion is that if you don't have #1, #2, #3, and #6 then it's
not Java. Not having #7 (and probably #4 too) will seriously restrict the
number of people that are willing to switch. Point #5 is easy to do (as groovy
has shown) and useful enough that you'd be stupid not to do it.
So really the point to question is #8. And while it's useful, and I think
we'd all like to keep it, the question has to be "Is it important enough to
hold back the evolution of the language (and platform) ?"