views:

7412

answers:

11

What's the best way to determine if the version of the JRE installed on a machine is high enough for the application which the user wants to run? Is there a way of doing it using java-only stuff? I'd like the solution to work on Windows/Linux/MacOSX - if the JRE version is too low a message should be displayed. Currently I'm getting an exception if i try to run it on Java 1.5 (the app is built for Java 1.6). If there's no universal solution, what's the best way to do it on Windows?

A: 

An application built for a higher-version JRE will not run on a lower-version JRE. So you wouldn't be able to just add code to your application to check the JRE version - if the JRE version was incompatible, your JRE-version-checking code would not run in the first place.

What you'd have to do is have some sort of launcher application that is built for a lower-version JRE (1.3?) that checks the version and then launches your app if necessary. This sounds kind of kludgy to me.

What about checking the version during installation? Are you installing the app in a way that allows you to check environment variables, or do any sort of scripting?

matt b
This isn't necessarily true. In most cases it will work fine. It's only if you're using more recent language or API features than trouble will ensue.
fiddlesticks
Not true. If I compile a simple Hello World application with JDK 1.6, and attempt to run it with JDK 1.4, I get an UnsupportedClassVersionError. What you are saying would only work if I compiled with 1.6 but specified -target 1.4.
matt b
Still, what stops you from compiling main class with 1.3, do all checks in it, and then call the rest of the application (1.6, for instance)?
Vladimir Dyuzhev
You need to compile your launcher class (and any custom classes it calls before the check) with something like "-source 1.2 -target 1.2" to force it to emit compatible bytecode. This means that in these classes you can't use modern features.
ddimitrov
@Vladimir - nothing is stopping from having a 1.3 launcher and a 1.6 main app. I was only commenting on a single-application solution.
matt b
+2  A: 

Generally, we've approached this with a C or (when unix-only) shell wrapper. Not sure this will really work for you.

We also approach this by embedding the JRE in our product. Takes care of 99.9% of the cases (the other 0.1% of the time is a user explicitly changing our configuration to use a different JVM). Again, not sure that this is a reasonable solution for you.

In our case, there is significant amounts of native code (JNI and otherwise), so tailoring an installable image for each platform we support is required anyway. But if you're dealing with a pure-Java solution, you may simply have to document your minimum and tell people to get with the program (no pun intended) if they're to run your stuff. It's sorta like people complaining that my Mac won't run MSVC, or that my Linux box is having problems running World of Warcraft. That's just not the (virtual) machine the software is targeted for - you need to switch. At least in the Java world, we really can call this an upgrade, though, without hurting anyone's OS-religious feelings. (Try telling the Mac user to "upgrade" to Windows XP to run MSVC - there's a beat-down waiting to happen.)

Tanktalus
A: 

System.getProperties() gives you a listing of JVM properties including the different version ids of the JRE, JVM and specification. This implemented for all versions of Java so should work regardless of version compiled in and version run in, or the implementation.

If you write a basic class to test the version, you can call this first in your main() launching class. It must really be basic functionality though or you might risk breaking it.

Spencer K
+4  A: 

You might also consider using Commons-Launcher, which allows you to setup various environment settings, or perform pre-checks before calling your application.

http://commons.apache.org/launcher

Spencer K
A: 

For the launcher - Check the version in there.

Inside the APP; as above use System.getProperties();

Properties sProp = java.lang.System.getProperties();
String sVersion = sProp.getProperty("java.version");
sVersion = sVersion.substring(0, 3);
Float f = Float.valueOf(sVersion);
if (f.floatValue() < (float) 1.4) {
    System.out.println("Java version too low ....");
    System.exit(1);
}
...
jim
This is VERY IFFY. If it's not that EXACT version, or they didn't install it in that location, or you are not running windows, it will fail. A modification that MIGHT work is to pipe the output of java -v into something and analyze that, but it will still be difficult to find a version "or later".
Bill K
And look what he asked for - linux/win/mac platforms or at least windows.Most corporate stuff is installed in the "exact location". linux and mac do the same thing.
jim
+2  A: 

You could do this using reflection and two compilers. Compile a main class with the oldest java version you want to be able to run at all with. It checks the version using System.getProperty("java.version"), or whatever, and then uses reflection to load your real main class if that check passes, possibly even loading the jar directly. The JRE shouldn't load any classes that weren't referenced by your outer main class at compile time.

TREE
You don't necessarily need two compilers. The Java-Compiler supports a -target-Option, that allows you to specify the Bytecode-version of produced class-files.
Mnementh
A: 

Hmm .. call me a boring guy, but what's wrong with using Launch4J or any other native launcher, for instance.

Use a native launcher to check the JVM version before actually running your code. Java only solutions (in my book) only make sense when you deal with developers; once you hit end-users, you'll realize that they dont care about Java or its technical details at all. If you would have written your application in GW-Basic they would not care less as long as your application works.

If Java 1.6 is not installed, lauchner4j will point the user to the download page for JDK 1.6. Thats probably more suitable for your problem than doing magic in Java.

+4  A: 

You might consider Java Webstart. Even if the name implies something like applets, it's about standalone-applications. Webstart is a launcher, that checks a JNLP-file (a simple XML-file, where you configure the download-location of your app, the needed Java-version and some other metadata) and starts your app with the correct JRE. It even updates the application, if a newer version is available. The downside is, you have to write a JNLP-file. Here is an example:

<?xml version="1.0" encoding="utf-8"?>

<!--
###############################################################################
#
# @(#)draw.jnlp 1.6 02/09/11
#
# JNLP File for Draw Demo Application
#
###############################################################################
 -->


<jnlp spec="0.2 1.0"
      codebase="http://java.sun.com/javase/technologies/desktop/javawebstart/apps"
      href="draw.jnlp">
   <information> 
      <title>Draw 4 App</title> 
      <vendor>Sun Microsystems, Inc.</vendor>
      <homepage href="http://java.sun.com/javase/technologies/desktop/javawebstart/demos.html"/&gt;
      <description>A minimalist drawing application along the lines of Illustrator</description>
      <description kind="short">Draw Demo Short Description</description>
      <icon href="images/draw.jpg"/>
      <offline-allowed/> 
   </information> 
   <resources>
      <j2se version="1.3+" href="http://java.sun.com/products/autodl/j2se"/&gt;
      <j2se version="1.3+"/>
      <jar href="draw.jar" main="true" download="eager"/>
   </resources>
   <application-desc main-class="Draw"/>
</jnlp>

A second possibility is to use a launcher-program. An example is the Apache Commons Launcher. You can also write some launcher app yourself, but that's usually not worth the effort.

Mnementh
A: 

I find that WinRun4J works quite well for me (but then again I may be biased since I wrote it:-)). This lets you specify a minimum and/or maximum version of java allowed. It will pop up a message box to the user if a suitable JRE version is not found (and the message is customisable).

Peter Smith
+1  A: 

You can require a Java version when running the Java command, e.g. java -version:1.6* com.me.MyClass. Not sure if this works on all releases of Java, but it works OK on 1.6 anyway.

lrussell
A: 

Have a launching class compiled for Java 1.2 which invokes the real main() in your 1.6 classes. If an unsupported class exception is thrown them catch it and display a nice error message.

Thorbjørn Ravn Andersen