“error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory” ‘java -version’ error on Startup

The Problem

“java -version” quits with the error message “error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory” when trying to start the JVM.

Case 1

The problem is there if it is run under a normal user or if it is run under the root user

$ java -version
[PATH_TO]/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

Case 2

The problem is there only if it is run by a normal user. There is no problem if it is run under the root user.

Under a normal user:

$ java -version
[JAVA_HOME]/bin/java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

Under root:

# [JAVA_HOME]/bin/java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

Solution for Case 1

Either only the Java binary was hard copied to a folder (e.g. /usr/bin/) without copying the rest of the JRE or JDK directories or just a hardlink of the Java binary was created in the folder (e.g. /usr/bin/).

# cp [JAVA_HOME]/jre/bin/java /usr/bin/

If the Java launcher binary cannot find the files of the JRE/JDK, it will fail to start the JVM. The libjli.so is dynamically linked to the Java binary. It is one of the first libraries that the Java launcher tries to load. The Java launcher is required to be able to read all of Java’s associated libraries in order to start properly.

There are 2 ways this can be resolved:

Solution 1

Create a symbolic link instead of a hardlink or a copy if you want to call Java from the /usr/bin folder.

# sudo ln -s [path to the JRE's java binary] /usr/bin/java
Note: Linux systems that support the command “update-alternatives” should use solution 2 below instead of creating a symlink.

Solution 2

use update-alternatives command as per the post below to set the correct java path.

Solution for Case 2

There are 2 scenarios here:

Scenario 1

The “setcap” command has been used to give the Java binary the proper permission to allow unprivileged users special rights. For example, to open ports lower than 1024:

# setcap cap_net_bind_service=+ep /bin/java

When raising the privileges of an executable, the runtime loader (rtld), better known as ld.so, will not link with libraries in untrusted paths. This is the way ld.so(1) was designed. If such an executable needs to be run, then the paths to the associated libraries for the elevated executable must be added to the trusted paths of ld.so.

Scenario 2

The JDK/JRE was installed under a different user account (e.g root) and world read permissions have been removed explicitly from either only the libjli.so or even the entire JDK or JRE directory structure. Example:

# chmod -R o-r [JAVA_HOME]

If the user who starts Java doesn’t have permissions to read the libjli.so library, Java will fail. This is because libjli.so is dynamically linked to the Java binary. Java must be able to read all of its dynamically linked libraries in order to start properly.

Solution for Scenario 1

There are 2 solutions here:

1. Remove the capability from the Java binary again:

# setcap -r [JAVA_HOME]/bin/java

Verify that java -version is working now:

$ [JAVA_HOME]/bin/java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

2. Create a file such as this, with the path to libjli.so:

$ cat /etc/ld.so.conf.d/java.conf
[JAVA_HOME]/jre/lib/amd64/jli
Note: If you use a 32-bit JRE, replace amd64 with i386.

This will add that path to the trusted user path that ld.so will use. It may be required to build the runtime cache. Verify if ld.so is seeing it by doing the following. The commands need to run as root. A reboot may be necessary.

# ldconfig | grep libjli
libjli.so -> libjli.so
.......

Verify that java -version is working now:

$ [JAVA_HOME]/bin/java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

Solution for Scenario 2

Restore read permissions so that the libjli.so and other files from the JDK/JRE directories can be read by the user. For example:

# chmod -R o+r [JAVA_HOME]

Verify that java -version is working now:

$ [JAVA_HOME]/bin/java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
Related Post