9

I am interested in using some of the NIO2 features in the Java 7 SDK if available (specifically, the file system watchers), however I do not want to compile my classes for Java 7 and exclude Java 6 runtimes. Mostly because I want retain compatibility with Mac OS X, and also because I don’t want to force my users to upgrade.

Is this possible? What is the best way to do it? Any links or examples?

Here are some ways I can imagine: compiling a class file with a different compiler and loading it dynamically based on the Java version? Or maybe using reflection? Or maybe there’s just a compiler setting for Java 7 to generate Java 6-compatible classes?

I am looking for a solution that doesn’t turn into an ugly mess :), so ideally I can write two implementations of an interface, one using the new features and one without, and then select one dynamically instead of having to do reflective calls all over the place.

Laurens Holst
  • 20,156
  • 2
  • 29
  • 33
  • Since I presume these features began to exist in SE7, how do you think you'll be able to compile with a SE6 compatibility mode and retain them? – KevinDTimm Sep 29 '11 at 14:29
  • What I want to do is only use them when the program is executed on a Java 7 runtime, and fall back on other behaviour if not. Note that I’m talking about Java 7 SDK features, not language features. – Laurens Holst Sep 29 '11 at 14:32
  • Sorry, two code bases are going to be necessary (or, at least, have a separate file handling base for each environment and create separate outputs for each version as code compiled in Version X typically doesn't work in any lower numbered Version) – KevinDTimm Sep 29 '11 at 14:35
  • java 6 runs on java 7 VM (but AFAIK not the other way around) – KevinDTimm Sep 29 '11 at 14:45

4 Answers4

9

Just build with -target 1.6 and organize your code so you can catch the ClassNotFoundExceptions and NoClassDefFoundErrors cleanly around the modules that use 1.7. Maybe load them with a separate class-loader for example.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • It works, thanks! I configured JDK 7 in Eclipse to take care of the syntax highlighting, and I built with target Java 6. For method calls that don’t exist you gotta catch the NoSuchMethodError. – Laurens Holst Sep 30 '11 at 08:27
  • @Laurens @EJP. I don't get it, how could you build source 1.7 with -target 1.6? Wouldn't it give you: `javac: source release 1.7 requires target release 1.7` – Pacerier Jan 15 '12 at 13:18
  • @Pacerier The trick is to build with source 1.6 instead of 1.7, and just invoke the methods from the 1.7 SDK. May need some configuration in your editor to prevent it from complaining and get code completion to work, but otherwise it just works. – Laurens Holst Jan 16 '12 at 12:54
  • @Pacerier Where exactly did I say anything about -source 1.7? – user207421 Feb 11 '13 at 22:43
1

You can build for java 1.6 easily as toolkit has pointed out. However, you need to make sure that you don't accidentally access any methods which don't exist in java 6. This will cause a runtime exception in your production code.

If you're using maven, you can use the maven-enforcer-plugin which makes sure that no java 1.7 classes or method calls sneak into your code built for 1.6.

An example would be the change from java 1.4 to 1.5. I was building with 1.5 with a target of 1.4, and I accidentally used:

new BigDecimal(5);

This compiled fine, and ran fine for me. But because the client was still using 1.4, it failed. Because this constructor doesn't exist in 1.4. It was introduced in 1.5.

Another solution would be to build a couple of jars, one with the new nio stuff, one with the old stuff, and detect at installation time whether or not the user was running java 1.7. If so, add the jar that contains the appropriate implementation.

Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
0

For some elements that were added in Java 7, you might be able to find Java 6 jsr jars that give you the functionality. I do not believe this will be the case for the File System Watcher however.

John B
  • 32,493
  • 6
  • 77
  • 98
  • If running on Java 6, I don’t need the functionality, it is optional for users running on Java 7. In this particular case, I will probably fall back on polling or explicit refresh behaviour. – Laurens Holst Sep 29 '11 at 14:41
0

In terms of file system watchers, before Java 7 I used to just poll a file's properties every few seconds or so to check it hadn't changed. It's not exactly nice, but practically it uses no noticeable resources and from an end user's perspective appears to work the same.

If you're after a more comprehensive library, check out http://commons.apache.org/jci/commons-jci-fam/index.html - I believe that does something similar, though I've never used it.

Specifying source 1.7 and target 1.6 I'm pretty sure won't work, I tried it for a different reason a while back and from memory the JVM complained about incompatible flags (my guess is because of the new invokedynamic in 7.)

Michael Berry
  • 70,193
  • 21
  • 157
  • 216