3

I have two Ubuntu 20.04 servers, Alpha and Beta, both with Tomcat 9 installed from the standard repo. In principle, they should be virtually identical, but I've found a discrepancy in which version of Java each uses that I can't find the origin of.

On server Alpha, both the ps process listing for Tomcat and systemctl status tomcat9.service show that its Java binary is /usr/lib/jvm/java-8-openjdk-amd64/bin/java. On server Beta, the same commands show that Tomcat's Java binary is /usr/lib/jvm/default-java/bin/java, which is a symlink to /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java.

Thus, server Alpha uses Java 8, while server Beta uses Java 11. They should be identical, yet something is clearly different.

The obvious question at this point is, how does Tomcat determine which version of Java to use?

1) Documentation

I cannot find the answer to this question in the Tomcat configuration documentation, and there are no other top-level topics in the documentation that seem relevant to this question.

2) Stack Overflow

This Stack Overflow question is the best I can find on the site, and it doesn't have any useful answers for an Ubuntu system; /etc/sysconfig/tomcat{N} is mentioned in one answer, but it does not exist on either server, while /etc/default/tomcat{N} exists on both but does not contain any parameters relating to Java version.

3) Standard config files

I have also checked the main Tomcat config file /var/lib/tomcat9/conf/server.xml and the Tomcat systemd service file /lib/systemd/system/tomcat9.service, but neither contain any parameters relating to Java version. Both servers have a service file override /etc/systemd/system/tomcat9.service.d/override.conf, but since I wrote that myself, I'm certain it doesn't set the version of Java used.

4) setenv.sh

Tomcat's /usr/share/tomcat9/bin/catalina.sh file mentions a JAVA_HOME environment variable, which I have to assume is what I'm looking for. That file appears to expect this variable to be set when it sources one of two files, $CATALINA_BASE/bin/setenv.sh or $CATALINA_HOME/bin/setenv.sh. Neither of these files (or bin/ directories, even) exist on either server, so this can't explain the difference.

That's all I can figure out. The question is:

In the absence of explicit user configuration, what determines what Java version Tomcat uses? This information must be stored in one of the files in Tomcat's installation, but I have no way of knowing which one.

EDIT

As @Emerson Pardo suggested, the two instances of Ubuntu 20.04 did have different default Java versions. After changing Beta's to use Java 8 using the Debian/Ubuntu update-alternatives program and restarting Tomcat, however, the problem outlined above is unchanged. Tomcat continues to use

/usr/lib/jvm/default-java/bin/java -> /usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java

on Beta.

Borea Deitz
  • 379
  • 4
  • 11
  • 2
    Is it specific to Tomcat? If you run `java --version` on both servers, what do you get? – Gaël J Jun 11 '21 at 18:29
  • @GaëlJ `java --version` on Alpha gives an error `Unrecognized option: --version`. On Beta, it gave `openjdk 11.0.11 2021-04-20` until I tried @Emerson Pardo's suggestion. Now it gives `Unrecognized option: --version`. See my first comment on that answer, it seems to be Tomcat-specific. – Borea Deitz Jun 11 '21 at 20:34
  • Okay, the version check must have changed between Java 8 and 11. For 8, it's `java -version`, with one dash, and it gives `openjdk version "1.8.0_292"` on both servers. – Borea Deitz Jun 11 '21 at 20:40

2 Answers2

4

On derivatives of Debian 10, such as Ubuntu 20.04, Tomcat is started through a wrapper script located in /usr/libexec/tomcat9/tomcat-start.sh. If you don't set JAVA_HOME yourself a heuristic procedure is performed in /usr/libexec/tomcat9/tomcat-locate-java.sh:

    # This function sets the variable JDK_DIRS
    find_jdks()
    {
        for java_version in 11 10 9 8
        do
            for jvmdir in /usr/lib/jvm/java-${java_version}-openjdk-* \
                          /usr/lib/jvm/jdk-${java_version}-oracle-* \
                          /usr/lib/jvm/jre-${java_version}-oracle-* \
                          /usr/lib/jvm/java-${java_version}-oracle \
                          /usr/lib/jvm/oracle-java${java_version}-jdk-* \
                          /usr/lib/jvm/oracle-java${java_version}-jre-*
            do
                if [ -d "${jvmdir}" ]
                then
                    JDK_DIRS="${JDK_DIRS} ${jvmdir}"
                fi
            done
        done
    }

    # The first existing directory is used for JAVA_HOME
    JDK_DIRS="/usr/lib/jvm/default-java"
    find_jdks

    # Look for the right JVM to use
    for jdir in $JDK_DIRS; do
        if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
            JAVA_HOME="$jdir"
        fi
    done
    export JAVA_HOME

Therefore:

  • if /usr/lib/jvm/default-java exists it is chosen,
  • otherwise the highest (up to 11) version of Java is used.
Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
2

Generally, Ubuntu chooses what Java it will be used by default. You can find it like this:

$ which java
/usr/bin/java
$/usr/bin/java --version
openjdk 11.0.11 2021-04-20                                                                                                                                                         
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.18.04)                                                                                                                
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.18.04, mixed mode, sharing)     

You can also check the alternatives available in your system using:

$ update-java-alternatives -l 

which will list all java installed.

To choose a specific version you can use:

$ sudo update-alternatives --config java
Emerson Pardo
  • 151
  • 1
  • 9
  • Thanks, I didn't know about this, and it turned out that the two Ubuntu installations had different default Java symlinks. However, even after setting both servers to use Java 8 in the manner you suggest, and restarting Tomcat, Tomcat still uses `/usr/lib/jvm/default-java/bin/java` as its Java version, and that still symlinks to Java 11. There appears to still be a Tomcat-specific difference between the two servers. – Borea Deitz Jun 11 '21 at 20:30
  • Check the item 3.4 of this documentation: http://tomcat.apache.org/tomcat-9.0-doc/RUNNING.txt. You will have to set JAVA_HOME in the `setenv.sh`. For example: `JAVA_HOME="/usr/lib/jvm/path-to-your-java8"` – Emerson Pardo Jun 11 '21 at 20:45
  • I don't have an active `setenv.sh` on either server (as far as I can tell), so that doesn't explain it. I know that I can use `setenv.sh`, but this question is limited to determining the cause of the discrepancy as it exists now. – Borea Deitz Jun 11 '21 at 20:52
  • Maybe another application (maybe the java installer) have set up the JAVA_HOME for the system. Try this: `echo $JAVA_HOME`. If it prints a path, check the version: `path-from-the-echo/bin/java -version` – Emerson Pardo Jun 11 '21 at 20:56