Java 21 is a Long-Term Support release that brings virtual threads, record classes, and pattern matching to the platform, making it the recommended JDK for new enterprise workloads on RHEL 9. Red Hat ships OpenJDK 21 through the standard dnf repositories, so installation is straightforward and kept in sync with security advisories. This tutorial covers installing OpenJDK 21, managing multiple Java versions with alternatives, setting JAVA_HOME permanently, building and running a Java application, and running a JAR as a systemd service.

Prerequisites

  • RHEL 9 server with a user that has sudo privileges
  • Active Red Hat subscription or equivalent repository access
  • Basic familiarity with the Bash shell

Step 1 — Install OpenJDK 21

RHEL 9 includes the OpenJDK packages in the AppStream repository. Install both the runtime and the developer kit so you can compile source files.

sudo dnf install -y java-21-openjdk java-21-openjdk-devel

# Confirm the installed packages
rpm -qa | grep java-21

Verify that the JVM and compiler respond correctly:

java -version
# openjdk version "21.0.3" 2024-04-16 LTS

javac -version
# javac 21.0.3

Step 2 — Manage Multiple Java Versions with alternatives

RHEL’s alternatives system lets you switch the default Java binary when more than one JDK is installed without altering PATH manually.

# List all registered java alternatives and choose the active one
sudo alternatives --config java

# If you also installed multiple javac versions, switch those too
sudo alternatives --config javac

The interactive prompt shows each registered JVM with a number; type the number for Java 21 and press Enter.

Step 3 — Set JAVA_HOME Permanently

Many Java tools and build systems require the JAVA_HOME environment variable. Create a profile drop-in that derives the correct path dynamically from whichever alternative is currently active.

sudo tee /etc/profile.d/java.sh <<'EOF'
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export PATH=$PATH:$JAVA_HOME/bin
EOF
sudo chmod 644 /etc/profile.d/java.sh
source /etc/profile.d/java.sh

Confirm the variable is set correctly:

echo $JAVA_HOME
# /usr/lib/jvm/java-21-openjdk-21.0.3.0.9-1.el9.x86_64

ls $JAVA_HOME/bin/java

Step 4 — Install Maven and Build a Hello World Application

Maven is available in the RHEL 9 AppStream repository and is the most common build tool for Java projects.

sudo dnf install -y maven
mvn --version

Compile and run a quick Hello World without Maven first to confirm the JDK is working:

mkdir -p ~/javatest && cd ~/javatest

cat > Hello.java <<'EOF'
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello from OpenJDK " +
            Runtime.version().feature() + " on RHEL 9!");
    }
}
EOF

javac Hello.java
java Hello
# Hello from OpenJDK 21 on RHEL 9!

Step 5 — Package the Application as a Runnable JAR

Bundle the compiled class into a JAR with a manifest that declares the entry point so it can be executed with java -jar.

mkdir -p myapp/META-INF
cp Hello.class myapp/

cat > myapp/META-INF/MANIFEST.MF <<'EOF'
Manifest-Version: 1.0
Main-Class: Hello
EOF

jar cfm hello.jar myapp/META-INF/MANIFEST.MF -C myapp .
java -jar hello.jar

Step 6 — Run the JAR as a systemd Service

For production deployments, run the JAR under systemd so it starts on boot, restarts on failure, and writes logs to the journal.

sudo mkdir -p /opt/myapp
sudo cp hello.jar /opt/myapp/

sudo tee /etc/systemd/system/myapp.service <<'EOF'
[Unit]
Description=My Java Application
After=network.target

[Service]
Type=simple
User=nobody
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -Xms128m -Xmx512m -jar /opt/myapp/hello.jar
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
sudo systemctl status myapp.service
journalctl -u myapp.service -n 30

Conclusion

You have installed OpenJDK 21 on RHEL 9 from the official AppStream repository, used the alternatives system to manage multiple JDK versions, set JAVA_HOME permanently via a profile drop-in, compiled and packaged a Java application as a runnable JAR, and registered it as a systemd service that starts automatically on boot.

Next steps: How to Deploy a .NET Application on RHEL 9, How to Install Go and Build CLI Tools on RHEL 9, and How to Install and Use Podman with systemd Socket Activation on RHEL 9.