12

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?

Vladimir Prenner
  • 227
  • 2
  • 4
  • 13

13 Answers13

11

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
  • 1,292
  • 2
  • 12
  • 21
  • 2
    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 Oct 22 '08 at 14:18
  • Thanks. This line works. I load the program and verify the String with the version the program needs. – elcool Jan 03 '12 at 19:14
9

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"/>
      <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"/>
      <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
  • 50,487
  • 48
  • 148
  • 202
5

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 Kormos
  • 8,381
  • 3
  • 28
  • 45
2

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.

lucrussell
  • 5,032
  • 2
  • 33
  • 39
2

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
  • 21,664
  • 5
  • 41
  • 68
1

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
  • 138,234
  • 66
  • 282
  • 345
  • 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. – PEELY Oct 21 '08 at 15:06
  • 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 Oct 21 '08 at 16:59
  • 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 Oct 21 '08 at 18:48
  • 2
    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 Oct 21 '08 at 23:01
  • @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 Oct 22 '08 at 14:27
  • I don't know why this is the accepted answer. If your application is packaged win a JAR you just need to compile a thin main class with a low java version, do the checking, the call your "main" main class which is compile with some other version. – Christian Fries Sep 13 '13 at 11:20
1

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
  • 1,502
  • 12
  • 23
  • 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 Oct 21 '08 at 16:49
  • 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 Oct 22 '08 at 09:38
1

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
  • 73,784
  • 33
  • 194
  • 347
1

Here is the code to get the JRE version installed in a system.

var list = deployJava.getJREs();
var result = "";
result = list[0];
for (var i=1; i<list.length; i++)
{
    result += ", " + list[i];
} 
document.write("jre version : "+result);
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
utpal
  • 11
  • 1
0

All those above is too damn complicated. Just go:

Properties props = System.getProperties()
props.list(System.out)

And you will see everything about your JVM, JRE, JDK and staff. Or get a specific value by using:

//full list of possible props you can see if u run code above
String props = System.getProperty(prop)
0

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 Kormos
  • 8,381
  • 3
  • 28
  • 45
0

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.

0

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
  • 753
  • 6
  • 7