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