New Java 7 language features should be backwards compatible

The discussion about new language features in Java SE 7 is on again, with abundant feedback to JavaPolis presentations on closures[2] and several "little" language features (like improved generic type inference, catch clauses, String switch, typedef and others). I am a supporter of the current closures proposal[3], but no matter which of these features you like, there's one aspect I see no one discussing: compatibility with older JVMs...

Right NOW, I am just starting to use J2SE 5.0's features, like generic types or java.util.concurrent, in my bigger projects. The reason is that large corps are slow, and they use application servers from even slower vendors... As a project architect, I'd love to send an email to my clients today, informing that our projects are moving to Java SE 6 and Glassfish V2 (or other up-to-date server) next week - we'll even do that migration for free!! because my life will become much better afterwards... but no, this is obviously not an option.

So that's the real world: I'm just starting to use Java 5. Java 6 is a distant dream - IBM's JDK 6 just went gold after an year-long beta, but there is no WebSphere update yet to include the new JDK, I guess I'll have to wait another 1-2 years until this update is fully complete, supported, tested, endorsed, and available in my clients' production servers. So when it comes to Java 7, well, I think I'll be happy if I can use that in large-scale, mission-critical applications (with IBM gear anyway), before I retire...

The real problem is that Java 5's language features were implemented with too many ties to the J2SE 5.0 platform: -source 5 will only accept -target 5. There's an unsupported javac switch that will allow some generics to target 1.4. But javac could do much better, as proven by third-party tools like RetroWeaver and JBoss Retro. (Similar support from javac would be much simpler than in those tools; javac could generate alternative code for older JVMs straight away, instead of generating 5.0-only bytecode that needs to pass through complex bytecode transformations to be replaced by alterenative code.) But it's also hopeles to use these tools in the environments I deal with. These translators have two severe problems:

1) They are not official tools. If I propose to use these things, my client's first question will be "is this supported by [insert large app server vendor here]?".
2) They make the edit/compile/deploy/debug cycle even more complex. I have systems with several dozen EARs and over a hundred projects, and I depend on the productivity of IDEs that update deployment into servers, automatically and quickly, and these IDEs have no flexibility to add a bytecode post-processor anywhere (but correct me if I am wrong, it's been some time since I last checked these tools).

So, my #1 wish for Java SE 7, whatever is the set of new language features that we decide to implement, is: make a best effort to support these features with -target 5, or at the very least -target 6. All features proposed to date are in the category of syntax sugar that's easily compilable into bytecode that current JVMs can load. Of course there's always some corner casees, like J2SE 5.0's enums which required new serialization support in the guts of the Java core; or in the same release, generics requiring new reflection APIs. So even if the proposals for Java SE 7 require special runtime support, there are several workarounds:

- Generating different code for older JVMs, even if it's slower (good solution when the runtime support is only an optimization).
- Backporting the new runtime support to the older JVMs, but making it private - for example, repackaging new APIs into sun.* packages, and translating calls to these APIs.
- Proving compatibility jars that can be dropped in older JREs' lib/endorsed. BTW, this could also be a great solution for critical new core APIs. See the backport-util-concurrent project[4] for a good example - but it shares the same problems of being a non-official, non-supported package (although it's easier to sneak into projects: just drop the jar in your EAR's /lib and don't tell anyone...).