Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know

Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know
Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know

Oracle announced it will stop releasing public updates of Oracle JDK in January 2019 and will require a commercial license for its use. An alternative is to useOpenJDKand effort is underway to make them fully interchangeable . A number of companies who are currently using Oracle JDK in production are making the decision to switch to OpenJDK or have already done so.

Andrew Haley (Red Hat’s Java Platform Lead Engineer) recently wrote a great article on the direction of OpenJDK .

In this article, I’ll discuss: the technical and support implications of the migration, what developers and operations teams need to know, and solutions to potential challenges.

I’ll go over the Red Hat support model and technical details of how to install, update, and run different OpenJDK versions on Red Hat Enterprise Linux (RHEL) 6 and 7 systems. I’ll also discuss the operations ofJava applications (such as Red Hat JBoss Enterprise Application Platform (JBoss EAP) and other servers) on top of OpenJDK.

While this article is about OpenJDK on RHEL, I should also point out thatOpenJDK for Windows can also be downloaded from developers.redhat.com. This lets you use the same JDK for Linux and Windows.

Architectural overview

A common configuration with Oracle JDK is for development teams to bundle Oracle JDK together with the application and only update the JDK if there is a security patch, bug fix, or new feature available in the new JDK.

OpenJDK, on the other hand, is not available as zip file (at time of writing). Instead, it is installed via yum , dnf , or rpm , with yum being therecommended method. Multiple concurrent major versions on the same server are fully supported (see below).

For businesses, this generally means that maintenance and updates to OpenJDK are handled by the infrastructure team (or someone with root access) instead of by the development team.

You should also be mindful about OpenJDK updates. While multiple major versions are supported (1.7, 1.8), yum will generally update the system to the latest minor build of each major version. (1.8 b60 -> 1.8 b191) and, by default, only the latest minor build is left installed. If you need multiple minor (build) versions installed concurrently, see thesection for minor versionsbelow.

Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know
Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know

Everything you need to grow your career.

With your free Red Hat Developer program membership, unlock our library of cheat sheets and ebooks on next-generation application development.

SIGN UP
Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know
Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know

Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know
Migrating from Oracle JDK to OpenJDK on Red Hat Enterprise Linux: What you need to know

Some customers have access to Oracle JDK SE via a content repository from Red Hat. However, in lieu of Oracle’s licensing changes, after the 30th of Nov. 2018, packages will not be available anymore . For OpenJDK installation instructions, see the instructions below.

Support options

Major LTS OpenJDK versions (7, 8,  and 11) on RHEL are fully supported by Red Hat and Red Hat is committed to providingcode-level patches for bug fixes. Major versions are supported for at least 6 years. For instance, OpenJDK 1.8 is supported untilJune 2023. OpenJDK isTCK-compliant and Red Hat tests and supports Java EE implementations such as the JBoss Enterprise Application Platform running on OpenJDK .

For full details, see the OpenJDK Life Cycle and Support Policy .

How to install OpenJDK and which packages are relevant

OpenJDK comes with a number of rpm packages. Only the first three are relevant for RHEL production servers.

On RHEL7, they can be found in the rhel-7-server-rpms repo.

java-1.8.0-openjdk.x86_64          # To execute java applications.
java-1.8.0-openjdk-devel.x86_64    # For compilation of Java. javac etc.. 
java-1.8.0-openjdk-headless.x86_64 # no audio/video. Just SE. E.g for embedded systems

For developers running RHEL/Fedora, you may also want to install the following packages:

java-1.8.0-openjdk-javadoc.noarch  # Javadoc that can be included in your IDE.
java-1.8.0-openjdk-src.x86_64      # Java sources, to review api implementation.

The installation is business as usual. I generally install the development package (to be able to compile applications) and it’ll pull in the required dependencies. (Seethis article if you need to enable sudo .)

$ sudo yum install java-1.8.0-openjdk-devel.x86_64

Sometimes I use ssh to access a server and I want to know which JDK is installed and is in the PATH . To tell Oracle JDK and OpenJDK apart, OpenJDK has “openjdk” in the version output:

$ java -version
openjdk version "1.8.0_171 # OpenJDK

$ java -version
java version "1.8.0_171 # OracleJDK

How to install and use multiple “major” versions of OpenJDK

Major versions are 7, 8, and 11   (aka 1.7, 1.8…). Multiple major versions on the same system arefully supported (in the context that each major version is updated to the latest minor version).

Installation is business as usual:

# List installed and available packages:
$ sudo yum list *openjdk* 

# Install desired version(s):
$ sudo yum install java-1.7.0-openjdk-devel.x86_64
$ sudo yum install java-1.8.0-openjdk-devel.x86_64

Now, for selecting which one to use, you have the choice to

  1. Use alternatives to select the default Java version on your system.
    This is a good option if you want to be able to select the default Java version for your entire system.
  2. Hard-code the  JAVA_HOME path manually to a symlink that points to the latest minor version.
    This is useful if you want to ensure an application always starts with a particular version of Java, independent of the default Java version on the system.

Option 1: Setting the default Java via alternatives

alternatives instructs the system which Java to use for the whole system.

You shouldn’t change this during the execution of Java to start another application with a different Java version. To do that, usebelow instead.

A common pitfall for developers is to set the default version of Java, but not to set the Java compiler (javac). If you’re compiling Java applications on the server, make sure to set both.

$ sudo alternatives --config java  # for running java applications.
$ sudo alternatives --config javac # for compiling java applications.
$ sudo alternatives --list # show available alternatives.

As a sanity check, I like to test with a mini “hello world” Java application that outputs the Java version.

$ cat jdkVersions.java 
   public class jdkVersions { 
      public static void main(String[] args) { 
        System.out.println("This app runs on: " + System.getProperty("java.version")); 
      } 
   } 
$ javac jdkVersions.java # this creates a jdkVersions.class 
$ java jdkVersions 
This app runs on: 1.8.0_191

For full details of alternatives and the support of major versions, see  Can I install multiple versions of java on a Red Hat Enterprise Linux system?

Option 2:  Hard-coding the  JAVA_HOME path

You can set the JAVA_HOME path as follows.

# Under '/usr/lib/jvm/' you can find symlinks that point to the latest java versions.
# You will find jre-1.8.0-openjdk and java-1.8.0-openjdk. The 'java' one is the one you need if you compile things. E.g:

$ export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk   # or 1.7 etc.. 
$ export PATH=$JAVA_HOME/bin:$PATH

# Validate via:
$ java -version
openjdk version "1.8.0_191"
$ javac -version
javac 1.8.0_191

How to install and use a particular or multiple “minor” versions of OpenJDK

In an ideal world, you would generally always update RHEL and you’d update OpenJDK to the latest minor version (for example, update 1.8 build 60 to 1.8 build 191).

But sometimes in your production environment, you run multiple Java applications and you’re unable to migrate them all to the latest version of OpenJDK at the same time or a build update breaks something. In such a case, you need to run your Java application on a particular build or you need to have multiple builds on the system.

As a warning, while this is technically possible, from a support point of view, generally Red Hat will support multiple LTS major versions, but only the latest minor version will be supported with patches if there are JVM crashes or other JVM issues. That is, Red Hat support will generally ask you if the issue can be reproduced with the latest minor build.

Another point to consider is that Java uses some underlying system libraries. When you update RHEL, the underlying libraries get updated, which may impact older minor builds. You should avoid the situation where you never update your JDK and the JDK becomes (for example) over a year behind the OS. That is, using an older minor build should only be a short-term situation while Dev or QA is validating the app against the newest build.

In other words, you should always aim to keep your applications on the newest minor build, similar to always waking up on time in the morning. If that’s simply not possible, run a particular build or run multiple minor builds, as described below.

Running a particular build and preventing updates

# List all versions:
$ sudo yum list available --showduplicates java-1.8.0-openjdk-devel.x86_64

Package name                    Versions
java-1.8.0-openjdk-devel.x86_64 1:1.8.0.31-2.b13.el7
java-1.8.0-openjdk-devel.x86_64 1:1.8.0.151-1.b12.el7_4
...

# Install the version you want by specifying (package name)-(version) where 'version' doesn't contain the '1:' prefix. E.g
$ sudo yum install java-1.8.0-openjdk-devel-1.8.0.191.b12-0.el7_5

# You can then exclude OpenJDK from yum updates either manually or by configuring /etc/yum.conf (see link below).
$ sudo yum update --exclude=java-1.8.0-openjdk*

See also exclude kernel or other packages from getting updated in RHEL .

Running multiple minor builds and preventing automatic removal of older packages

Typically when updating a package, the latest matching version is installed and any previous versions are removed. It is recommended to always run just the latest minor version that has the most up-to-date security and bug fixes.  However, there are times when you’d like to have multiple versions installed concurrently.  With RHEL 7, you can prevent yum from automatically removing the older versions.  (Note: In RHEL 6, this is not possible. I’ve tried; you get rpm version conflicts and the Red Hat development team confirmed that this is expected behavior.)

OpenJDK 1.7 and 1.8 are considered separate packages, because they are different major versions.

Finally, while running multiple minor versions is technically possible, only the latest minor version will be supported if there are JVM crashes or issues.

To get around this, you can instruct yum to keep old versions of particular packages, in our case, OpenJDK:

# edit /etc/yum.conf and append the following:
installonlypkgs=java-1.8.0-openjdk,java-1.8.0-openjdk-headless,java-1.8.0-openjdk-devel

# Now you can install Java packages per the instructions above and list installed versions via:
# rpm -qa | grep java-1.8.0-openjdk

# you should see multiple OpenJDK versions if you've installed multiple ones.

# Now you may wish to hard-code JAVA_HOME to a particular Java minor version. E.g:
$ export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.151-5.b12.el7_4.x86_64
$ export PATH=$JAVA_HOME/bin:$PATH

# Validate via:
$ java -version
openjdk version "1.8.0_151"
$ javac -version
javac 1.8.0_151

For details, please see How to install multiple minor versions of OpenJDK on a Red Hat Enterprise Linux system?

Are there known issues or incompatibilities, or does OpenJDK lack something that Oracle JDK has?

Oracle JDK 11 and OpenJDK 11 will be interchangeable .

There are some differences between Oracle JDK 1.8 and OpenJDK 1.8, although the gap is shrinking.

For example, Mission Control has been open sourced recently . I know a software engineer in our Toronto, Canada, office who recently started working on it. Java Flight Recorder was also open sourced and will be available in JDK 11. VisualVM has been open source for a while and as of JDK 9 it is no longer shipped with the JDK but is available as a separate open source project .

I’ve heard there are plans to make them available via rpm in the future as part of OpenJDK 11.

While OpenJDK 1.8 is SE-compliant, Oracle JDK has some additional features, which should be taken into account.

For example, JavaFX code may require some work. There is OpenFX , though.

I’ve been asked whether Java’s Cryptography/Security extension (JCE) is supported in OpenJDK. The answer isyes it is, although for legal reasons, you need to download the unlimited strength files manually from Oracle . Also see theinstallation notes.

Sometimes I get asked if monitoring agents are compatible with OpenJDK (for example, AppDynamics). In general, most tools are compatible, although you need to check if all features are compatible.

The general approach is to try to switch your application to OpenJDK (via JAVA_HOME ), re-compile and see if there are any compile / test issues and go from there.

What about OpenShift?

Red Hat provides container images with OpenJDK as base images. See the article Getting Started with OpenShift Java S2I to learn more about source-to-image container builds.

I hope this article helps. If you have some other questions, please post a comment and I’ll try my best to answer.