In this article, you’ll learn how to install and run simple Java applications on Red Hat Enterprise Linux (RHEL) 8, how to switch between two parallel installed major JDK versions via alternatives
, and how to select one of the two JDKs on a per-application basis.
Four major versions of Java are supported in RHEL 8: Java 21, 17, 11, and Java 8. In this article, I’ll refer to Java 21 as JDK (Java Development Kit) 21 since we are focusing on the development aspect of using Java. JDK 21 refers to Red Hat build of OpenJDK 21. The same applies to other JDK versions.
TL;DR: Install Java on RHEL
To install JDK 21 on RHEL 8, use:
$ sudo yum install java-21-openjdk-devel
(If you didn't, select Make this user administrator during install; see this article on how to enable sudo on RHEL).
Then, run Java "Hello World" as follows:
$ cat > HelloWorld.java <<HELLO
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
HELLO
$ javac HelloWorld.java && java HelloWorld
Hello World!
To install JDK 17 on RHEL 8, use:
$ sudo yum install java-17-openjdk-devel
Then, run Java “Hello World” as follows:
$ cat > HelloWorld.java <<HELLO
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
HELLO
$ /usr/lib/jvm/java-17-openjdk/bin/java HelloWorld.java
Hello World!
Yes, with JDK 11 and above, you can directly run Java source files. The compilation step is handled for you.
Video demo
If you prefer to watch a short 4-minute demo video, here it is:
The longer version
Let's consider we have a freshly commissioned Red Hat Enterprise Linux 8 machine and we'd like to use it for running Java applications.
How to find available Java packages
In order to figure out which RPM packages to install, we can ask the packaging system which ones provide the java
binary:
$ yum provides \*/bin/java
This command tells us that packages java-21-openjdk-headless
, java-17-openjdk-headless
, java-11-openjdk-headless
and java-1.8.0-openjdk-headless
all provide the java
binary. For the purpose of this article, we’re interested in the development kits, so we’ll install the -devel
sub-packages instead. The -devel
packages will pull in -headless
packages as a dependency. If you already know that RHEL packages are OpenJDK builds, yum list available
might be useful, too:
$ yum list available \*openjdk\*
For the purpose of this article, we are going to install JDK 21 and JDK 17 in parallel, and also install Maven:
$ sudo yum install java-21-openjdk-devel java-17-openjdk-devel maven
Switch Java versions
In the previous step, we installed JDK 21 and JDK 17 in parallel. At this point in time, JDK 8 is the main JDK on RHEL 8. That’s why you get this output when running java -version
on a fresh RHEL 8 install even though you didn't install JDK 8 explicitly:
$ java -version openjdk version "1.8.0_422" OpenJDK Runtime Environment (build 1.8.0_422-b05) OpenJDK 64-Bit Server VM (build 25.422-b05, mixed mode)
There are two ways to select the Java version you want:
- Switch
java
andjavac
binaries system wide via alternatives. This approach requires root privileges. - Select the JDK on a per-application basis by setting
JAVA_HOME
.
Select Java versions with alternatives
java
and javac
binaries on RHEL 8 are managed by the alternatives
system. This means a system administrator can switch the system java
(or javac
) to be something other than the default, JDK 8. The alternatives
system uses priorities in order to determine which JDK should be available via /usr/bin/java
. JDK 8 has been given a higher priority on RHEL 8 than other JDKs. But we are getting ahead of ourselves. First, let's see which binaries are managed by alternatives:
$ alternatives --list
We see that java
and javac
are managed by alternatives. Next, we are going to switch to JDK 21, using the alternatives --config
command:
$ sudo alternatives --config java There are 3 programs which provide 'java'. Selection Command ----------------------------------------------- 1 java-17-openjdk.x86_64 (/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el8.x86_64/bin/java) *+ 2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.el8.x86_64/jre/bin/java) 3 java-21-openjdk.x86_64 (/usr/lib/jvm/java-21-openjdk-21.0.4.0.7-1.el8.x86_64/bin/java) Enter to keep the current selection[+], or type selection number: 3
This will switch the system java
binary to JDK 21. We do the same for javac
since java
and javac
are independently managed. There is no need to switch anything else as every other JDK binary will switch either with the java
or the javac
binary:
$ sudo alternatives --config javac There are 3 programs which provide 'javac'. Selection Command ----------------------------------------------- 1 java-17-openjdk.x86_64 (/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el8.x86_64/bin/javac) *+ 2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.el8.x86_64/bin/javac) 3 java-21-openjdk.x86_64 (/usr/lib/jvm/java-21-openjdk-21.0.4.0.7-1.el8.x86_64/bin/javac) Enter to keep the current selection[+], or type selection number: 3
Switch alternatives non-interactively
Here is an approach to switch to JDK 21, via alternatives, using non-interactive means, which comes in handy if you need to script it:
$ JAVA_21=$(alternatives --display java | grep 'family java-21-openjdk' | cut -d' ' -f1) $ sudo alternatives --set java $JAVA_21
Similarly, switching to JDK 8 via alternatives by non-interactive means:
$ JAVA_8=$(alternatives --display java | grep 'family java-1.8.0-openjdk' | cut -d' ' -f1) $ sudo alternatives --set java $JAVA_8
A similar approach can be followed for javac
.
Select Java versions by setting JAVA_HOME
Many applications support using the JAVA_HOME
environment variable, as a way to specify which JDK should be used to run the application. The examples below demonstrate this usage when running maven. This approach is handy if you don’t have root privileges, but both JDKs are already installed on your system.
Selecting JDK 21:
$ JAVA_HOME=/usr/lib/jvm/java-21-openjdk mvn --version
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 21.0.4, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk-21.0.4.0.7-1.el8.x86_64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.18.0-513.5.1.el8_9.x86_64", arch: "amd64", family: "unix"
Selecting JDK 17:
$ JAVA_HOME=/usr/lib/jvm/java-17-openjdk mvn --version
Apache Maven 3.5.4 (Red Hat 3.5.4-5)
Maven home: /usr/share/maven
Java version: 17.0.12, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el8.x86_64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.18.0-513.5.1.el8_9.x86_64", arch: "amd64", family: "unix"
This feature also comes in handy if you have multiple minor JDK versions installed as Leo Ufimtsev described in his article for RHEL 7.
Launch single-file source code programs in JDK 11 and later
With JEP 330, part of JDK 11 and later, it’s possible to run Java code in a script-like fashion. The feature is called Launch Single-File Source-Code Programs, and it lets you use Java as scripting language. Here is a simple example:
$ cat > factorial <<FACT
#!/usr/lib/jvm/java-11-openjdk/bin/java --source 8
public class Factorial {
private static void usage() {
System.err.println("factorial <number>");
System.exit(1);
}
private static long factorial(int num) {
if (num <= 1) {
return 1;
}
if (num == 2) {
return 2;
}
return factorial(num - 1) * num;
}
public static void main(String[] args) {
if (args.length != 1) {
usage();
}
int num = -1;
try {
num = Integer.parseInt(args[0]);
} catch (Exception e) {
System.err.println("Error: Argument not a number!");
usage();
}
System.out.println(factorial(num));
}
}
FACT
$ chmod +x factorial
$ ./factorial 6
720
Thank you. I hope you’ve found this article useful.
Last updated: September 3, 2024