Hi there,

I did some small tests using OpenSSL/Panama with TC 10.1.23 for running the unit tests.

First: they seem to work well using JDK 22 with OpenSSL 3.0.13, 3.1.5, 3.2.1 and 3.3.0. For JDK 23 the tests are still running, but also look good up to now.

But some things around native library loading in the JVM seem to be nasty in principle:

1) Library file name
====================

First some (well-known) background info about shared library loading in Linux in general:

When one *compiles* a binary or shared object against a library using "-lsomelib" the compile time linker looks for a file named libsomelib.so. It tries to resolve all symbols needed but not defined in the object to compile in these libs. If all goes well, it records the library dependency in the resulting object as NEEDED. This record does not refer to "libsomelib.so" as a name, but instead the so called SONAME of libsomelib.so. That's an internal name of the library often reflecting an API stability version. For example for OpenSSL 3.x the SONAME of libssl.so is libssl.so.3.

Now during runtime of the compiled object the runtime linker notices the need for the recorded SONAME (NEEDED libssl.so.3). It then searches a file with *that* name. In the OpenSSL example it is libssl.so.3, not (!) libssl.so.

On a "normal" linux system, libssl.so is therefore not installed, only libssl.so.3 (if OpenSSL 3 is installed at all). The file libssl.so (or better the symlink) is only part of the devel package typically installed on development systems, because it is only needed during compile time, not during runtime.

Now back to the JVM:

The Java API to load a native library (for example System.loadLibrary(String name)) gets the library name as a String parameter. What is this library name? Unfortunately the JVM devs did not do a good job. If you pass the API the String "somelib", they simply prepend it with "lib" and append ".so" and try to load that file. For example when you pass "ssl", they look for libssl.so. There is no way to tell Java to look for libssl.so.3 using this API. On a normal system, the file libssl.so does not exist and should not exist, because it is a development file.

As a workaround one has to provide libssl.so, at least as a symlink to libssl.so.3.

2) Indirect dependencies
========================

Normally libssl.so(.3) has dependencies itself, e.g. for libcrypto.so.3 (NEEDED libcrypto.so.3). These dependencies are not longer loaded via the Java API but implicitly by the runtime linker. So now, you do not need a file libcrypto.so - you can't even make that work - you really need the file libcrypto.so.3. Very confusing for newbies and pretty inconsistent.

3) java.library.path
====================

The system property java.library.path is only used by the JVM when loading the libs requested via the Java API, so here libssl.so. The runtime linker looking then for libcrypto.so.3 is not set up to use java.library.path. So if the libs are not installed in a default system location, you need to set LD_LIBRARY_PATH to point to your libcrypto. If libssl is in the same directory (pretty much always), you then won't need java.library.path at all, because LD_LIBRARY_PATH also influences the search of libssl.so by the Java API. Again confusing.

None of this is Tomcat's fault. They are all deficiencies of the (old) Java APIs which were IMHO misdesigned. It might be different on Windows or Macs.

Just wanted to mention it in case others run into the same nits. We might want to document something though before raising more awareness for using OpenSSL via panama.

Best regards,

Rainer

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to