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
sudoprivileges - 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.