Getting Java version at runtime - java

I need to work around a Java bug in JDK 1.5 which was fixed in 1.6. I'm using the following condition:
if (System.getProperty("java.version").startsWith("1.5.")) {
...
} else {
...
}
Will this work for other JVMs? Is there a better way to check this?

java.version is a system property that exists in every JVM. There are two possible formats for it:
Java 8 or lower: 1.6.0_23, 1.7.0, 1.7.0_80, 1.8.0_211
Java 9 or higher: 9.0.1, 11.0.4, 12, 12.0.1
Here is a trick to extract the major version: If it is a 1.x.y_z version string, extract the character at index 2 of the string. If it is a x.y.z version string, cut the string to its first dot character, if one exists.
private static int getVersion() {
String version = System.getProperty("java.version");
if(version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if(dot != -1) { version = version.substring(0, dot); }
} return Integer.parseInt(version);
}
Now you can check the version much more comfortably:
if(getVersion() < 6) {
// ...
}

What about getting the version from the package meta infos:
String version = Runtime.class.getPackage().getImplementationVersion();
Prints out something like:
1.7.0_13

Runtime.version()
Since Java 9, you can use Runtime.version(), which returns a Runtime.Version:
Runtime.Version version = Runtime.version();

These articles seem to suggest that checking for 1.5 or 1.6 prefix should work, as it follows proper version naming convention.
Sun Technical Articles
J2SE SDK/JRE Version String Naming Convention
Version 1.5.0 or 5.0?
"J2SE also keeps the version number 1.5.0 (or 1.5) in some places that are visible only to developers, or where the version number is parsed by programs"
"java.version system property"
Version 1.6.0 Used by Developers
"Java SE keeps the version number 1.6.0 (or 1.6) in some places that are visible only to developers, or where the version number is parsed by programs."
"java.version system property"

The simplest way (java.specification.version):
double version = Double.parseDouble(System.getProperty("java.specification.version"));
if (version == 1.5) {
// 1.5 specific code
} else {
// ...
}
or something like (java.version):
String[] javaVersionElements = System.getProperty("java.version").split("\\.");
int major = Integer.parseInt(javaVersionElements[1]);
if (major == 5) {
// 1.5 specific code
} else {
// ...
}
or if you want to break it all up (java.runtime.version):
String discard, major, minor, update, build;
String[] javaVersionElements = System.getProperty("java.runtime.version").split("\\.|_|-b");
discard = javaVersionElements[0];
major = javaVersionElements[1];
minor = javaVersionElements[2];
update = javaVersionElements[3];
build = javaVersionElements[4];

Example for Apache Commons Lang:
import org.apache.commons.lang.SystemUtils;
Float version = SystemUtils.JAVA_VERSION_FLOAT;
if (version < 1.4f) {
// legacy
} else if (SystemUtils.IS_JAVA_1_5) {
// 1.5 specific code
} else if (SystemUtils.isJavaVersionAtLeast(1.6f)) {
// 1.6 compatible code
} else {
// dodgy clause to catch 1.4 :)
}

Just a note that in Java 9 and above, the naming convention is different. System.getProperty("java.version") returns "9" rather than "1.9".

Does not work, need --pos to evaluate double:
String version = System.getProperty("java.version");
System.out.println("version:" + version);
int pos = 0, count = 0;
for (; pos < version.length() && count < 2; pos++) {
if (version.charAt(pos) == '.') {
count++;
}
}
--pos; //EVALUATE double
double dversion = Double.parseDouble(version.substring(0, pos));
System.out.println("dversion:" + dversion);
return dversion;
}

Here's the implementation in JOSM:
/**
* Returns the Java version as an int value.
* #return the Java version as an int value (8, 9, etc.)
* #since 12130
*/
public static int getJavaVersion() {
String version = System.getProperty("java.version");
if (version.startsWith("1.")) {
version = version.substring(2);
}
// Allow these formats:
// 1.8.0_72-ea
// 9-ea
// 9
// 9.0.1
int dotPos = version.indexOf('.');
int dashPos = version.indexOf('-');
return Integer.parseInt(version.substring(0,
dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
}

If you can have dependency to apache utils you can use org.apache.commons.lang3.SystemUtils.
System.out.println("Is Java version at least 1.8: " + SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));

Don't know another way of checking this, but this: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()" implies "java.version" is a standard system property so I'd expect it to work with other JVMs.

Here is the answer from #mvanle, converted to Scala:
scala> val Array(javaVerPrefix, javaVerMajor, javaVerMinor, _, _) = System.getProperty("java.runtime.version").split("\\.|_|-b")
javaVerPrefix: String = 1
javaVerMajor: String = 8
javaVerMinor: String = 0

https://docs.oracle.com/javase/9/docs/api/java/lang/Runtime.Version.html#version--
Runtime.version().version()
For 17.0.1 it returns [17, 0, 1]
One can use Runtime.version().version().get(0) to get the major java version.

In kotlin:
/**
* Returns the major JVM version, e.g. 6 for Java 1.6, 8 for Java 8, 11 for Java 11 etc.
*/
public val jvmVersion: Int get() = System.getProperty("java.version").parseJvmVersion()
/**
* Returns the major JVM version, 1 for 1.1, 2 for 1.2, 3 for 1.3, 4 for 1.4, 5
* for 1.5 etc.
*/
fun String.parseJvmVersion(): Int {
val version: String = removePrefix("1.").takeWhile { it.isDigit() }
return version.toInt()
}

Related

Maven version ordering for alpha and a

The answer https://stackoverflow.com/a/31482463/927493 explains the order of Maven versions. Following https://blog.soebes.de/blog/2017/02/04/apache-maven-how-version-comparison-works/, you can compare versions on the command line. I got the following results:
C:\coprogramme\apache-maven-3.5.0\lib>java -jar maven-artifact-3.5.0.jar 2.0.0 2.0.0-a
Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 2.0.0 == 2
2.0.0 < 2.0.0-a
2. 2.0.0-a == 2-a
C:\coprogramme\apache-maven-3.5.0\lib>java -jar maven-artifact-3.5.0.jar 2.0.0 2.0.0-alpha
Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 2.0.0 == 2
2.0.0 > 2.0.0-alpha
2. 2.0.0-alpha == 2-alpha
Following the answer and also the Javadoc in https://github.com/apache/maven/blob/master/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java, the version parts alpha and a should be equal, which is apparently not the case.
Can anyone explain this to me?
Despite what the documentation says, it appears that a is a synonym for alpha only when it is immediately followed by a digit. So
2.0.0-a1 is equivalent to 2.0.0-alpha1 and 2.0.0-alpha-1 (but not 2.0.0-alpha.1)
the a in 2.0.0-a, 2.0.0-a.1 or 2.0.0-a-1 is an "unknown qualifier", not equivalent to 2.0.0-alpha-1, and sorted after all the known qualifiers
The behaviour appears because ComparableVersion has two ways of defining aliases, in the inner class that deals with string components:
private static final List<String> QUALIFIERS =
Arrays.asList( "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" );
private static final Properties ALIASES = new Properties();
static
{
ALIASES.put( "ga", "" );
ALIASES.put( "final", "" );
ALIASES.put( "release", "" );
ALIASES.put( "cr", "rc" );
}
// ...
StringItem( String value, boolean followedByDigit )
{
if ( followedByDigit && value.length() == 1 )
{
// a1 = alpha-1, b1 = beta-1, m1 = milestone-1
switch ( value.charAt( 0 ) )
{
case 'a':
value = "alpha";
break;
case 'b':
value = "beta";
break;
case 'm':
value = "milestone";
break;
default:
}
}
this.value = ALIASES.getProperty( value , value );
}
A special-case scenario for single-letter qualifiers a, b, and m, that is only triggered if followedByDigit==true, and that only happens when the qualifier was terminated by the next character being a digit.
A list of aliases: ga, final and release are exactly equivalent to the empty string (with the latter being the canonical form), and cr's canonical form is rc. This part behaves as the OP expects.
I would guess that this is based on observed version usage, where sometimes letters are used literally as versions (e.g. OpenSSL used to use a trailing letter or two to number patch releases, such as 0.9.7m or 0.9.8zh), while alpha, beta and milestone releases always have a release number in practice, and projects using a short version aren't going to put any extra characters in: so a by itself meaning "alpha" never actually occurs.
It's a shame it's not documented properly!

How to programatically get all Java JRE(JVM) installed and its path using C++ language?

For example, there are 2 JVMs installed on a user's machine: JDK 5 JDK 6
and corresponding path should be outputted ?
If environment variables set, you can use std::getenv http://en.cppreference.com/w/cpp/utility/program/getenv
For example:
const char* PossibleEnvNames[] = { "JAVA_HOME", "JAVA_PATH", "JAVA" }; // ... etc.
for(int i = 0; i < sizeof(PossibleEnvNames); ++i) {
std::cout << std::getenv(PossibleEnvNames[i]);
}

Using navigator.plugins to determine Java version

The following javascript code will inform all your browser's enabled plugins (yeah, I know it doesn't work on IE, but for IE there's always deployJava):
if ((navigator.plugins) && (navigator.plugins.length)) {
for (var bb = 0, l = navigator.plugins.length; bb < l; bb++) {
var vv = navigator.plugins[bb].name + "<br>";
document.write(vv);
}
}
I have Java 6.22 installed so the relevant line written to the page is this:
Java(TM) Platform SE 6 U22
My question is: how can I complement the above code so that it returns the major version (6) and update (22) found in my (or anyone's) browser?
I think the best way is to work with regular expression, but I am not good with it.
I think the easiest (read: hackiest) solution would be something like this:
var plugin_name = navigator.plugins[bb].name
if (plugin_name.toLowerCase().indexOf("java") != -1) {
var parts = plugin_name.split(" ").reverse();
// if the plugin has an update
if(plugin_name.match(/U[0-9]+/)) {
// grab the end of the plugin name and remove non numeric chars
var update = parts[0].replace(/[^0-9]/, "");
// grab the major version and remove non numeric chars
var major = parts[1].replace(/[^0-9]/, "");
// print the major number and update number
console.log(major);
console.log(update);
} else {
var update = "0";
// grab the major version and remove non numeric chars
var major = parts[0].replace(/[^0-9]/, "");
// print the major number and update number
console.log(major);
console.log(update);
}
}
You can then throw this code in your loop through the plugins and replace the console.log with whatever logic is appropriate given a major and update number.

Check if Windows XP or later in Java?

What would be the easiest way to check that the operating system running my Java application is Windows XP or later?
EDIT: I know about System.getProperty("os.name") but I don't know the best way and/or most efficient way to check what version of Windows is running. Ideally, I would also like to make it future proof so that if another version of Windows is released I don't need to change the code.
mkyong has given a tutorial: http://www.mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/
It relies on System.getProperty("os.name")
Since Windows reliably reports its version information as a float, "XP or higher" can be calculated by knowing what each Windows version is and comparing.
The shorthand:
// Is this XP or higher?
// Well, XP Reports as 5.1 (32-bit) or 5.2 (64-bit). All higher OSs use a higher version
final boolean XP_OR_HIGHER = (Float.parseFloat(System.getProperty("os.version")) >= 5.1f);
But due to exceptions that can be raised with parsing a System value, combined with the fact that XP is EOL and it's more likely that someone is looking for a newer OS comparison... here's a more comprehensive way to do it.
Note: With Windows 10, all versions are reported as 10.0 regardless of how much Microsoft changed between releases. For finer detail, you will have to look into the registry (See also HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId).
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class WinVer {
enum WindowsType {
/*
* Keep descending for best match, or rewrite using comparitor
*/
WINDOWS_10(10.0f),
WINDOWS_8_1(6.3f),
WINDOWS_8(6.2f),
WINDOWS_7(6.1f),
WINDOWS_VISTA(6.0f),
WINDOWS_XP_64(5.2f),
WINDOWS_XP(5.1f),
WINDOWS_ME(4.9f),
WINDOWS_2000(5.0f),
WINDOWS_NT(4.0f), // or Win95
UNKNOWN(0.0f);
private float version;
WindowsType(float version) {
this.version = version;
}
public static float parseFloat(String versionString) {
float version = 0.0f;
/*
* Sanitize the String.
*
* Windows version is generally formatted x.x (e.g. 3.1, 6.1, 10.0)
* This format can later be treated as a float for comparison.
* Since we have no guarantee the String will be formatted properly, we'll sanitize it.
* For more complex comparisons, try a SemVer library, such as zafarkhaja/jsemver. <3
*/
List<String> parts = Arrays.asList(versionString.replaceAll("[^\\d.]", "").split("\\."));
// Fix .add(...), .remove(...), see https://stackoverflow.com/a/5755510/3196753
parts = new ArrayList<>(parts);
// Fix length
while (parts.size() != 2) {
if (parts.size() > 2) {
// pop off last element
parts.remove(parts.size() - 1);
}
if (parts.size() < 2) {
// push zero
parts.add("0");
}
}
String sanitized = String.join(".", parts.toArray(new String[0]));
try {
version = Float.parseFloat(sanitized);
} catch (NumberFormatException e) {
System.err.println("ERROR: Something went wrong parsing " + sanitized + " as a float");
}
return version;
}
public static WindowsType match(float version) {
WindowsType detectedType = UNKNOWN;
// Warning: Iterates in order they were declared. If you don't like this, write a proper comparator instead. <3
for (WindowsType type : WindowsType.values()) {
if (type.version >= version) {
detectedType = type;
} else {
break;
}
}
return detectedType;
}
}
public static void main(String... args) {
String osName = System.getProperty("os.name");
String osVer = System.getProperty("os.version");
if (osName.toLowerCase().startsWith("windows")) {
System.out.println("Yes, you appear to be running windows");
float windowsVersion = WindowsType.parseFloat(osVer);
System.out.println(" - Windows version reported is: " + windowsVersion);
WindowsType windowsType = WindowsType.match(windowsVersion);
System.out.println(" - Windows type is detected as: " + windowsType);
if(windowsVersion >= WindowsType.WINDOWS_XP.version) {
System.out.println("Yes, this OS is Windows XP or higher.");
} else {
System.out.println("No, this OS is NOT Windows XP or higher.");
}
}
}
}

In Java how to parse a string to a float and compare the value?

I have a small code snippet as shown below, which as you can see has a hard-coded value for checking server version.
Now my intention is, if the server version is 11.3.0 or higher, then the if should be entered, but i am not able to figure out a way, Integer.parseInt won't work i guess as i parses int not float.
String serverVersion = DatamodelVersion.getInstance().getVersion();
if(serverVersion.equalsIgnoreCase("11.3.0"))
{
outstr = new FileOutputStream(confFile);
prop.setProperty("NTFSDriver", "11.3.0/x86/tntfs.ko");
prop.setProperty("NTFSDriver_x64", "11.3.0/x86_64/tntfs.ko");
prop.store(outstr, "");
update = true;
System.out.println("Updated the tuxera conf file successfully");
logger.logDebugAlways("Updated the tuxera conf file successfully");
}
Try this
String serverVersion = DatamodelVersion.getInstance().getVersion();
String[] version = serverVersion.split("\\.");
if (Integer.parseInt(version[0]) > 11 || (Integer.parseInt(version[0]) == 11 && Integer.parseInt(version[1]) >= 3))
{
outstr = new FileOutputStream(confFile);
prop.setProperty("NTFSDriver", "11.3.0/x86/tntfs.ko");
prop.setProperty("NTFSDriver_x64", "11.3.0/x86_64/tntfs.ko");
prop.store(outstr, "");
update = true;
System.out.println("Updated the tuxera conf file successfully");
logger.logDebugAlways("Updated the tuxera conf file successfully");
}
there is not a built-in function in Java to transform 11.3.0 to float, because 11.3.0 is not a valid float number.
for strings containing a valid float number, you could use Float.valueOf in Java.
Split the version number by "."
Then compare one by one with your reference data.
String serverVersion = DatamodelVersion.getInstance().getVersion();
serverVersion.split('.')[0] // and so on..
A version number is neither an integer, nor a float. Your best bet is using a specialized class:
public class Version implements Comparable<Version> {
public Version(int major, int minor, int revision) {
// set fields
}
public int compareTo(Version other) {
// compare major minor and revision
}
public boolean equals(Object other) {
// code here
}
// parse a version in X.Y.Z form
static Version parse(String version) {
return new Version(//...);
}
}
Using this you may decide to later add support for versions like 1.3.4-ALPHA or -RC1 and the like.
You could try splitting the number into 3 parts, like so:
String[] bits = serverVersion.split(".");
Then, use a for loop and Integer.parseInt to parse each section of the number, and compare each.
You need to define your own method for checking version numbers, based on the rules these numbers must follow in your domain.
Based on the information you've provided, I would do a String split on . and compare each value in turn (as an integer) against 11, 3 and 0 respectively.
You have a Version class here : http://nvn.svn.sourceforge.net
It should be used like this
Version v = Version.parse(DatamodelVersion.getInstance().getVersion());
and store numbers in the standard format MAJOR.MINOR.BUILD.REVISION
11.3.0 is not a float number. What about to use following code instead:
int Compare(String ver1, String ver2)
{
String[] ver1s = ver1.Split("\.");
String[] ver2s = ver2.Split("\.");
if(ver1s.length > ver2.length) return 1;
if(ver2s.length > ver1.length) return -1;
for(int i = 0;i < ver1s.length;i++)
{
if(Integer.valueOf(ver1s[i]) > Integer.valueOf(ver2s[i])) return 1;
if(Integer.valueOf(ver2s[i]) > Integer.valueOf(ver1s[i])) return -1;
}
return 0;
}

Categories

Resources