skip to Main Content

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.

2

Answers


  1. 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
    
    Login or Signup to reply.
  2. 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.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search