Correct way to check Java version from BASH script
Asked Answered
O

20

79

How can I check whether Java is available (in the PATH or via JAVA_HOME) from a bash script and make sure the version is at least 1.5?

Octo answered 7/9, 2011 at 13:34 Comment(4)
Java 5 has been end-of-life for quite a long time. Java 6 will be end-of-life very soon. You should be moving to Java 6 as a priority, and to 7 as soon as you can.Maize
What have you tried?Davisdavison
@Brian: Nothing; My hope is that someone has a "bash search path function" handy.Octo
@kittylyst: This is a minimal requirement. My software doesn't need Java 6 features, so there is no point forcing users for something better. But thanks for pointing it out anyway.Octo
S
103

Perhaps something like:

if type -p java; then
    echo found java executable in PATH
    _java=java
elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]];  then
    echo found java executable in JAVA_HOME     
    _java="$JAVA_HOME/bin/java"
else
    echo "no java"
fi

if [[ "$_java" ]]; then
    version=$("$_java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
    echo version "$version"
    if [[ "$version" > "1.5" ]]; then
        echo version is more than 1.5
    else         
        echo version is less than 1.5
    fi
fi
Seifert answered 7/9, 2011 at 14:24 Comment(7)
Excellent. I was missing the type builtin.Octo
Ug sorry cant get comments to format. This fails when Java version is 1.10. This is because string comapre is not a number compare. Also the answer is wrong when version is "1.5" Though I guess that would be "1.5.0" so I guess its okay.Weatherby
good point. you could do something like: IFS=. read major minor extra <<<"$version"; if (( major == 1 && minor > 5 )); ... -- would have to check for invalid octal numbers like "08".Seifert
the "type -p java" won't work in "sh"; so, for portability, use #!/bin/bash in the script, rather than #!/bin/sh (though, it's possible that /bin/sh isn't actually bourne shell, but rather a backward compatible variant)Grimace
For comparing versions, I suggest : version1=$(echo "$version" | awk -F. '{printf("%03d%03d",$1,$2);}') which will get you major and minor aligned with 3 digit for each, and then compare with if [ $version1 -ge 001008 ] ; thenOwensby
Combining Glenn's original post with his comment above, I did the following to check for Java <=1.7 (in this case related to setting TLS defaults: IFS=. read major minor extra <<<$(java -version 2>&1 | awk -F '"' '/version/ {print $2}'); if [ $major -lt 1 -o $major -eq 1 -a $minor -le 7 ]; then JVM_EXTRA_OPTS="-Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1"; fiApportion
Boo, hiss for showing a string comparison instead of a version comparison.Comeback
C
53

You can obtain java version via:

JAVA_VER=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F '.' '{sub("^$", "0", $2); print $1$2}')

it will give you 16 for java like 1.6.0_13, 15 for version like 1.5.0_17, 110 for openjdk 11.0.6 2020-01-14 LTS and 210 for java version 21 2023-09-19 LTS.

So you can easily compare it in shell:

[ "$JAVA_VER" -ge 15 ] && echo "ok" || echo "too old"

UPDATE: This code should work fine with openjdk and JAVA_TOOL_OPTIONS as mentioned in the comments.

Cowitch answered 7/9, 2011 at 13:58 Comment(5)
The result of 'java -version' with OpenJDK 8 is slightly different, "java" is replaced by "openjdk" in the output. This expression works with both cases: sed 's/.*version "\(.*\)\.\(.*\)\..*"/\1\2/; 1q'Gratitude
If JAVA_TOOL_OPTIONS is set the output is again slightly different, the java version is not on the first line. eg: Picked up JAVA_TOOL_OPTIONS: -agentlib:hprof java version "1.7.0_60" Java(TM) SE Runtime Environment (build 1.7.0_60-b19) Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode) Dumping Java heap ... allocation sites ... doneEcclesiastes
EmmanuelBourg and codebuddy thanks. I updated code to fix issues you found.Assignable
This doesn't work correctly anymore since java 9, and fails spectacularly since java 10Unfolded
Some tweak to this as below should work after Java 9 as well... JAVA_VER=$(java -version 2>&1 | sed -n ';s/.* version "(.*)\.(.*)\..*"/\1\2/p;')Squab
B
31

The answers above work correctly only for specific Java versions (usually for the ones before Java 9 or for the ones after Java 8.

I wrote a simple one liner that will return an integer for Java versions 6 through 11 (and possibly all future versions, until they change it again!).

It basically drops the "1." at the beginning of the version number, if it exists, and then considers only the first number before the next ".".

java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1

Barber answered 21/5, 2019 at 16:52 Comment(0)
G
17

You can issue java -version and read & parse the output

java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'
Giorgia answered 7/9, 2011 at 13:36 Comment(4)
This is very close to what I want. Do you know of a version which also searches $PATH before it calls locate (which isn't always available)?Octo
both links dont work and I checked my internet twice :-)Isla
@Ravi, right I will edit those links, you could use java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}' by the timeGiorgia
If interested in the numerical part only and for further usage in path variables, you may use something like java -version 2>&1 | head -1 | cut -d '"' -f 2Unwisdom
L
11

You could also compare the jdk class version number with javap:

javap -verbose java.lang.String | grep "major version" | cut -d " " -f5

If its java 8, this will print 52, and 55 for java 11. With this you can make a simple comparison and you don't have to deal with the version string parsing.

Lachrymator answered 20/2, 2020 at 13:49 Comment(3)
This is a nice hack if you just want to know the major version. Sometimes, you'd like to check that a certain patchlevel is installed.Octo
Amazing, this is bullet proof !!Contumelious
Simple and easy for major version checkOsmium
S
9

I wrote a bash function that should work for JDK 9 and JDK 10.

#!/bin/bash

# returns the JDK version.
# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected
jdk_version() {
  local result
  local java_cmd
  if [[ -n $(type -p java) ]]
  then
    java_cmd=java
  elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
  then
    java_cmd="$JAVA_HOME/bin/java"
  fi
  local IFS=$'\n'
  # remove \r for Cygwin
  local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
  if [[ -z $java_cmd ]]
  then
    result=no_java
  else
    for line in $lines; do
      if [[ (-z $result) && ($line = *"version \""*) ]]
      then
        local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
        # on macOS, sed doesn't support '?'
        if [[ $ver = "1."* ]]
        then
          result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
        else
          result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
        fi
      fi
    done
  fi
  echo "$result"
}

v="$(jdk_version)"
echo $v

This returns 8 for Java 8 ("1.8.0_151" etc), and 9 for Java 9 ("9-Debian" etc), which should make it easier to do the further comparison.

Syringe answered 15/2, 2018 at 23:33 Comment(0)
A
5

Determining the Java version only using grep with Perl-style regex can be done like this:

java -version 2>&1 | grep -oP 'version "?(1\.)?\K\d+'

This will print the major version for Java 9 or higher and the minor version for versions lower than 9, for example 8 for Java 1.8 and 11 for Java 11.0.4.

It can be used like this:

JAVA_MAJOR_VERSION=$(java -version 2>&1 | grep -oP 'version "?(1\.)?\K\d+' || true)
if [[ $JAVA_MAJOR_VERSION -lt 8 ]]; then
  echo "Java 8 or higher is required!"
  exit 1
fi

The || true was added to prevent the script from aborting in case Java is not installed and the Shell option set -e was enabled.

Adenaadenauer answered 21/6, 2021 at 16:19 Comment(0)
E
4

A combination of different answers:

JAVA_VER=$(java -version 2>&1 | grep -i version | sed 's/.*version ".*\.\(.*\)\..*"/\1/; 1q')
  • Returns 7 for Java 7 and 8 for Java 8
  • Works with OpenJDK and with Oracle JDK
  • Works even if the JAVA_TOOL_OPTIONS is set
Elenaelenchus answered 3/11, 2016 at 17:17 Comment(3)
for Java 10, this returns '0' for the version numberGerianne
$ java -version 2>&1 | grep -i version | sed 's/.*version ".*\.(.*)\..*"/\1/; 1q' --> 0 for java version "9.0.1"Bevon
Indeed, answer below works better for java version > 9: https://mcmap.net/q/261686/-correct-way-to-check-java-version-from-bash-scriptElenaelenchus
N
3
  1. in TERMINAL
java -version |& grep 'version' |& awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'
  1. in BASH
#!/bin/bash


echo `java -version 2>&1 | grep 'version' 2>&1 | awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'`
jver=`java -version 2>&1 | grep 'version' 2>&1 | awk -F\" '{ split($2,a,"."); print a[1]"."a[2]}'`

if [[ $jver == "1.8" ]]; then                
     echo $jver is java 8
else
     echo $jver is java 11
fi

Works in SUN and Linux

Noah answered 3/2, 2020 at 9:35 Comment(1)
Small improvements: Use $(...) instead of backticks. They are safer, support nesting, and easier to type on most keyboards/OSs.Octo
S
2

The method I ended up using is:

# Work out the JAVA version we are working with:
JAVA_VER_MAJOR=""
JAVA_VER_MINOR=""
JAVA_VER_BUILD=""

# Based on: http://stackoverflow.com/a/32026447
for token in $(java -version 2>&1 | grep -i version)
do
    if [[ $token =~ \"([[:digit:]])\.([[:digit:]])\.(.*)\" ]]
    then
        JAVA_VER_MAJOR=${BASH_REMATCH[1]}
        JAVA_VER_MINOR=${BASH_REMATCH[2]}
        JAVA_VER_BUILD=${BASH_REMATCH[3]}
        break
    fi
done

It will work correctly even if JAVA_TOOL_OPTIONS is set to something due to filtering done by grep.

Spore answered 2/6, 2016 at 13:56 Comment(1)
Oneliner: if [[ $(java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}') =~ \"([0-9])\.([0-9])\.([0-9])_(.*)\" ]]; then echo ${BASH_REMATCH[2]}; fiTwist
K
2

Another way is: A file called release is located in $JAVA_HOME. On Java 15 (Debian) it has as content:

IMPLEMENTOR="Debian"
JAVA_VERSION="15.0.1"
JAVA_VERSION_DATE="2020-10-20"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.vm.ci jdk.management jdk.unsupported jdk.internal.vm.compiler jdk.aot jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.internal.opt jdk.jdeps jdk.jlink jdk.incubator.jpackage jdk.internal.le jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management.agent jdk.jconsole jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=""

So you see JAVA_VERSION, which contains the version number.

For example,

major=$(echo $JAVA_VERSION | cut -d. -f1)

sets major to the value 15 (=Major version number), which you can use further.

It's a really simple solution.

Killam answered 1/12, 2020 at 15:30 Comment(1)
Interesting. I found the file in several JDKs (Oracle and OpenJDK). I don't think it will exist in J9 or the Amazon JVM. Plus you need to figure out the Java installation folder if $JAVA_HOME isn't defined.Octo
B
2

Getting java version string, using Bash's built-in parsing capabilities:

#!/usr/bin/env bash

java_cmd=${1:-java}

# Captures version string between double-quotes
IFS='"' read -r _ java_version_string _ < <("${java_cmd}" -version 2>&1)

# Splits version string at dots and (underscore for patch number)
IFS='._' read -r \
  java_version_major \
  java_version_minor \
  java_version_build \
  java_version_patch \
  <<<"$java_version_string"

# Debug demo output
declare -p java_version_major java_version_minor java_version_build \
  java_version_patch

Examples

System default Java 17:

declare -- java_version_major="17"
declare -- java_version_minor="0"
declare -- java_version_build="3"
declare -- java_version_patch=""

Specific Java 8 path provided as argument:

declare -- java_version_major="1"
declare -- java_version_minor="8"
declare -- java_version_build="0"
declare -- java_version_patch="352"
Banquer answered 16/11, 2022 at 10:56 Comment(3)
I''m getting -bash: java_version_major: command not found for the line with the here string <<<.Octo
IFS="." read java_version_major java_version_minor java_version_build java_version_patch <<< "$java_version_string" works for me.Octo
@AaronDigulla I broke my answer with an unfortunate cut during an edit. It is now fixed.Kathlyn
V
1

I had a similar problem, I wanted to check which version of java was installed to perform two types of application launches. The following code has solved my problem

jdk_version() {
  local result
  local java_cmd
  if [[ -n $(type -p java) ]]
  then
    java_cmd=java
  elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
  then
    java_cmd="$JAVA_HOME/bin/java"
  fi
  local IFS=$'\n'
  # remove \r for Cygwin
  local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
  if [[ -z $java_cmd ]]
  then
    result=no_java
  else
    for line in $lines; do
      if [[ (-z $result) && ($line = *"version \""*) ]]
      then
        local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
        # on macOS, sed doesn't support '?'
        if [[ $ver = "1."* ]]
        then
          result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
        else
          result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
        fi
      fi
    done
  fi
  echo "$result"
}

_java="$(jdk_version)"
echo $_java

if [[ "$_java" > "$8" ]]; then
       echo version is more than 8

else
  echo version is less than 8

fi

source

I hope to be proved helpful

Vortical answered 1/1, 2019 at 12:25 Comment(2)
You should be able to replace the sed with BASH parameter expansion (gnu.org/software/bash/manual/html_node/…) using ${parameter/pattern/string}Octo
@AaronDigulla Thanks for the information, I will see the link and I update the answerVortical
R
1

There is a nice portable bash function for this here: http://eed3si9n.com/detecting-java-version-bash

jdk_version() {
  local result
  local java_cmd
  if [[ -n $(type -p java) ]]
  then
    java_cmd=java
  elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
  then
    java_cmd="$JAVA_HOME/bin/java"
  fi
  local IFS=$'\n'
  # remove \r for Cygwin
  local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
  if [[ -z $java_cmd ]]
  then
    result=no_java
  else
    for line in $lines; do
      if [[ (-z $result) && ($line = *"version \""*) ]]
      then
        local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
        # on macOS, sed doesn't support '?'
        if [[ $ver = "1."* ]]
        then
          result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
        else
          result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
        fi
      fi
    done
  fi
  echo "$result"
}
Rodge answered 21/9, 2020 at 10:24 Comment(0)
B
0

I know this is a very old thread but this will still be of help to others.

To know whether you're running Java 5, 6 or 7, firstly type java -version.

There will be a line in your output that looks similar to this: java version "1.7.0_55"

Then you use this table for converting the 'jargon' result to the version number.

1.7.0_55 is Java 7
1.6.0_75 is Java 6
1.5.0_65 is Java 5

Information taken from a page on the Oracle site
http://www.oracle.com/technetwork/java/javase/7u55-relnotes-2177812.html

Barrera answered 26/11, 2014 at 8:1 Comment(5)
This doesn't work if you have anything other than those specific minor versions of Java, e.g.Julietjulieta
Well. I got this information from a page on the official Oracle site. I don't know it all and neither do I pretend to. If you know what other versions of Java there are then feel free to add a subcomment with these underneath this message.Barrera
1.5.0_anything is Java 5, 1.6.0_anything is Java 6, 1.7.0_anything is Java 7, 1.8.0_anything is Java 8. The minor versions change all the time (though I suppose there aren't ever going to be any new ones for Java 5 or 6).Julietjulieta
Also, there's no guarantee anyone will have the most recent minor version.Julietjulieta
That's fair enough. Why didn't you just say that in the first place? I had a feeling that 1.x... meant version x but I didn't want to make that assumption in case I was wrong.Barrera
S
0

Using bashj, an extended bash version (https://sourceforge.net/projects/bashj/), you get a rather compact solution:

#!/usr/bin/bashj
echo System.getProperty("java.runtime.version")

The answer is provided by an integrated JVM (in ~0.017'' execution time for the script , and ~0.004'' for the call itself).

Selfsupporting answered 18/6, 2018 at 16:10 Comment(0)
F
0

I found the following works rather well. It is a combination of the answers from Michał Šrajer and jmj

version=$(java -version 2>&1 | sed -n ';s/.* version "\(.*\)\.\(.*\)\..*"/\1\2/p;' | awk '{ print $1 }').

I have openJDK 13 installed and without the awk command the first answer printed: 130 2020-01-14. Thus, adding awk '{ print $1 }' provides me with just the version.

Fuentes answered 21/1, 2021 at 14:43 Comment(0)
T
0

This question is still relevant so posting my answer.

Using slightly convoluted way by using built-in Bash variable expansions and avoiding creating multiple sub-shells

line=$(java -version 2>&1 | head -1) && echo ${${${line#*\"}#1.}%%.*}

Returns 8 for Java 1.8.0_312 and 17 for 17.0.6

This can be used in a script like below

#!/bin/bash

required=5

version=$(line=$(java -version 2>&1 | head -1) && echo ${${${line#*\"}#1.}%%.*})

[[ $version -ge $required ]] && echo "Java version OK" || echo "Java version too low"
Tussle answered 1/10, 2023 at 14:46 Comment(0)
T
0

You can get the process ID by using ps -ef | grep -v grep | grep java and then use jcmd process_id vm.version

Toponym answered 9/5 at 21:47 Comment(0)
C
0

One-liner to check for a minimum required Java version in bash:

(echo 'class a{public static void main(String[] a){}}' > a.java && java --source 17 a.java || a=$? ; (rm -f a.java ; exit $a))

The exitcode indicates if Java 17+ is available. Note that this requires a (temp) file a.java.

Celestyn answered 30/5 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.