2

I was wondering why mvn shows that Java version: 9.0.1, while my current java command is 1.8.0_151? Thanks.

$ mvn --version
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T03:58:13-04:00)
Maven home: /home/t/program_files/programming/Maven/apache-maven-3.5.2
Java version: 9.0.1, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-9-oracle
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.13.0-26-generic", arch: "amd64", family: "unix"

$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

Note that I have installed both java 8 and java 9:

$ update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).

  Selection    Path                                  Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-9-oracle/bin/javac   1091      auto mode
* 1            /usr/lib/jvm/java-8-oracle/bin/javac   1081      manual mode
  2            /usr/lib/jvm/java-9-oracle/bin/javac   1091      manual mode

$ update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                     Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-9-oracle/bin/java       1091      auto mode
* 1            /usr/lib/jvm/java-8-oracle/jre/bin/java   1081      manual mode
  2            /usr/lib/jvm/java-9-oracle/bin/java       1091      manual mode

and

$ which java
/usr/bin/java
$ readlink -f /usr/bin/java
/usr/lib/jvm/java-8-oracle/jre/bin/java

and the only part in $PATH is

/usr/lib/jvm/java-8-oracle/bin:
/usr/lib/jvm/java-8-oracle/db/bin:
/usr/lib/jvm/java-8-oracle/jre/bin

and

$ echo $JAVA_HOME
/usr/lib/jvm/java-9-oracle/

A solution which I don't quite understand:

$ export JAVA_HOME=/usr/lib/jvm/java-8-oracle/
$ mvn --version
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T03:58:13-04:00)
Maven home: /home/t/program_files/programming/Maven/apache-maven-3.5.2
Java version: 1.8.0_151, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.13.0-26-generic", arch: "amd64", family: "unix"

Does mvn rely only on JAVA_HOME, while java doesn't?

Tim
  • 1
  • 141
  • 372
  • 590
  • The `java` *8* executable is being found *first* in the PATH (this may be a symlink that is toggled between different "options"). `mvn` apparently is not using the standard PATH resolution (it is probably using JAVA_HOME). However, the shell that executes the `java` command *has no notion of JAVA_HOME* for the resolution. – user2864740 Jan 22 '18 at 03:28
  • Type `which java` to see where the java executable is found when you run it from the command-line. It be something other than `/usr/lib/jvm/java-9-oracle/bin/java` – Code-Apprentice Jan 22 '18 at 03:28
  • Try `export JAVA_HOME=/usr/lib/jvm/java-8-oracle/` to **actually** use Java 8 with maven (if that is what you want). – Elliott Frisch Jan 22 '18 at 03:32
  • @ElliottFrisch Thanks. (1) What are the differences between putting java related directories into `JAVA_HOME` and into `PATH`? (2) Does Maven only rely on `JAVA_HOME` to find `java` and `javac`? – Tim Jan 22 '18 at 03:49
  • @Tim 1) Depends on the program. It's not actually java. Maven is started by the command mvn. Which is a shell or batch *script*. 2) https://stackoverflow.com/a/25541714/2970947 – Elliott Frisch Jan 22 '18 at 03:53
  • @ElliottFrisch: does `update-alternatives --config javac` not affect `JAVA_HOME`? – Tim Jan 22 '18 at 03:57
  • @Tim [No](https://stackoverflow.com/a/23124799/2970947). – Elliott Frisch Jan 22 '18 at 04:00

3 Answers3

3

The mvn command is actually a shell script, and that script makes the decisions about which version of Java is used for the JVM that runs maven.

The thing that determines which JVM is uses are the $JAVA_HOME and / or $JAVACMD environment variables:

  • Normally, $JAVA_HOME from your environment is used to find the java command. Typically `$JAVA_HOME/bin/java" is used.

  • If $JVMCMD is set, that overrides $JAVA_HOME

  • If you have an /etc/mavenrc file, or a ~/.mavenrc, then these are "sourced" first. So they may override the settings of $JAVA_HOME, etc from your environment.

  • If $JAVA_HOME or $JAVACMD are not set explicitly, then the "mvn" script tries to find the "best" Java installation by platform specific means. You may or may not end up with the version selected via "alternatives" and/or the current setting of $PATH.

Also note the you can set Java versions in your POM file. These affect the source and target versions for the code you build, but they do NOT affect the version of the JVM that runs your builds. (So if you were to select Java 9 in your POM and try build with a Maven on Java 8 JVM, then Maven would give an error.)

Does mvn rely only on $JAVA_HOME, while java doesn't?

Basically, yes with a couple of nuances:

  • mvn has fall-back logic for the case where $JAVA_HOME is not set.
  • java actually depends on how you have configured your $PATH. If you put $JAVA_HOME/bin (or similar) ahead of /usr/bin in your $PATH, then the shell won't see /usr/bin/java and your "alternatives" setting will be ineffective. (The alternatives mechanism for Java works by installing symlinks to commands as /usr/bin/java, /usr/bin/javac and so on.)

Does update-alternatives --config javac affect $JAVA_HOME?

It doesn't. The alternatives system works by updating symbolic links.


Bottom line:

  • If you want to ensure that mvn uses a specific Java version (without interfering with anything else), export the appropriate JAVA_HOME variable in your mavenrc file.

  • If you want to really understand what is going on with mvn, read the script!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks. How does `update-alternatives --config somecommand` find the files for `somecommand`? Does it rely on `$PATH`? – Tim Jan 22 '18 at 13:07
  • It looks them up. The config information is in the /var/lib/alternatives directory. – Stephen C Jan 22 '18 at 15:00
  • Thanks for this info. Now it makes a lot of sense and it fixed my issues. In the end I just had to remove `~/.mavenrc`, because it did more harm than good. My problem was with Java 11 btw – D.Bronder Mar 11 '19 at 10:26
2

Why does mvn show that Java version: 9.0.1, while my current java command is 1.8.0_151?

The short answer is because you have two different versions of Java installed. When you type java from the command line, it uses one version. mvn finds the other version.

You can see which java executable is used by typing

which java

The output from mvn shows that it is using the JDK installed at /usr/lib/jvm/java-9-oracle.

The command-line uses the PATH environment variable to search for executable files when you type a command. You can see the value of it by typing

echo $PATH 

If both directories for Java 8 and Java 9 appear in the PATH, then the shell will use the first one found. You can tweak the order of PATH, but it is probably best just to remove the one that you don't want to use by default.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Thanks. How is `PATH` relevant here? – Tim Jan 22 '18 at 03:49
  • @Tim `PATH` is relevant because shell use it to resolve location of `java` binary. BTW you can use strace to findout what is going on `strace -f -e execve java -version` and `strace -f -e execve mvn -version` – rkosegi Jan 22 '18 at 03:54
  • @Tim When you type a command, the shell searches each directory in `PATH` for an executable by that name. It then runs the first one it finds. In this case, your Java 8 installation is in the PATH and either Java 9 is not at all or it is later in the list. `mvn` uses its own configuration (of which I have no knowledge of the details) to determine which SDK to use. Since the two use different mechanisms to find the `java` executable, they can easily find different ones. – Code-Apprentice Jan 22 '18 at 03:58
2

Does mvn rely only on JAVA_HOME, while java doesn't?

Yes, maven use $JAVA_HOMEenvironment variable to find java installation while terminal always refer $PATHto find executable files in the system.

PATH is an environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, specifying a set of directories where executable programs are located

So if you need to change the java version which is referred by maven, you have to change the $JAVA_HOME variable.

Or else take a look at How to change maven Java version in pom.xml

does update-alternatives --config javac not affect JAVA_HOME?

No. See this

Chathura Buddhika
  • 2,067
  • 1
  • 21
  • 35