Skip to main content

Mixing class file versions

3 replies [Last post]
pajatopmr
Offline
Joined: 2004-09-18

I would like to use SystemTray (a 1.6 feature) in an application that could well be run on 1.5 JVMs. In order to do so, I think I have to target compile the main class to 1.5 and in that main class test the JVM version. If the JVM version is 1.6 then it is safe to load the classes compiled with 1.6 features. And if I am not mistaken the 1.6 compiled class must be loaded explicitly.

Will this approach work? Are there any other gotchas I need to be aware of? When is it likely that ~80% of existing computers will have 1.6 installed? Is it too heavy handed to install 1.6 automagically when installing the app?

Thanks,

-pmr

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
here_he_is_javanet
Offline
Joined: 2005-11-20

I do something similar with reflection to support the Substance look and feel under stand-alone applications that run in Java 1.3.1 to Java 1.5+.

My typical code for this looks like:

[i]Class cls = Class.forName("org.jvnet.substance.watermark.SubstanceImageWatermark");

Class partypes[] = new Class[1];

File f = new File("logo.jpg");

boolean exists = (f.exists() && f.canRead());

// If a local file exists, then use that
// otherwise, use the logo.jpg image bundled in the JAR file
if (exists) {
partypes[0] = String.class;
}else
partypes[0] = InputStream.class;

Constructor ct = cls.getConstructor(partypes);

Object arglist[] = new Object[1];

if (exists) {
arglist[0] = new String("logo.jpg");
}else {
arglist[0] = new Run().getClass().getResourceAsStream("logo.jpg");
}

Object retobj = ct.newInstance(arglist);

Class cls2 = Class.forName("org.jvnet.substance.SubstanceLookAndFeel");
Class paramClassType = Class.forName("org.jvnet.substance.watermark.SubstanceWatermark");

Class partypes2[] = new Class[1];
partypes2[0] = paramClassType;
Method meth = cls2.getMethod("setCurrentWatermark", partypes2);

Object arglist2[] = new Object[1];
arglist2[0] = retobj;
meth.invoke(retobj.getClass(),arglist2);

javax.swing.UIManager.setLookAndFeel("org.jvnet.substance.SubstanceLookAndFeel");

[/i]
This is equivalent to the code:

[i]File f = new File("logo.jpg");

boolean exists = (f.exists() && f.canRead());

// If a local file exists, then use that
// otherwise, use the logo.jpg image bundled in the JAR file
if (exists) {

SubstanceImageWatermark Image = new org.jvnet.substance.watermark.SubstanceImageWatermark("./logo.jpg");
else { SubstanceImageWatermark Image = new org.jvnet.substance.watermark.SubstanceImageWatermark(new Run().getClass().getResourceAsStream("logo.jpg"));
}

SubstanceLookAndFeel.setCurrentWatermark(Image);

That should give you an idea how to use reflection to define classes and pass parameters through to classes using reflection.

jwenting
Offline
Joined: 2003-12-02

You would indeed have to load the 1.6 dependent classes by name, and refer to them only through an interface compiled against 1.5.

If you did that it MIGHT work, but then again it may not (I've never tried anything of the kind, would be an interesting experiment).

>When is it likely that ~80% of existing computers will have 1.6 installed
Depends entirely on your target audience.
Most of our customers are still using 1.4, some are still on 1.3.
I don't expect the last of those to be using 1.5 for several years yet, 1.6 maybe in a decade or so.

coxcu
Offline
Joined: 2003-06-11

I think it's easier than you make it sound. That's especially true if you're willing to add something like BeanShell, so you can write code that looks like normal Java, but really uses reflection under the covers, thus bypassing many issues. With that said, if you intend to support multiple environments, you need to test on multiple environments.