System.loadLibrary and CLinker.lookup exception
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Apr 27 08:35:31 UTC 2022
Late to this thread.
Just wanted to provide some background here.
The way to search library symbols in Panama is via a SymbolLookup.
So, in SymbolLookup you will find (e.g. in the preview version of the
API), different ways to obtain a lookup and get started:
1) loader lookup: this searches for symbols in all libraries loaded with
System.load/loadLibrary _by the current class loader_. Does not allow
for same library to be loaded in multiple loaders.
2) libraryLookup(Path/String): this loads a library, searches symbols in
it. When the associated scope is closed, the library is unloaded. Allows
same library to be loaded in multiple loaders.
3) system lookup - this is currently exposed by CLinker itself, which
implements SymbolLookup. The idea behind this being an instance method
in CLinker is that different linkers might expose different "standard"
libraries.
I think the confusion in this thread, as pointed out by Radoslaw is
caused by the fact that (3) is defined in a slightly asymmetric way -
e.g. it is not a factory in SymbolLookup. Being an instance method in
CLinker, it seems like it can cause developers to completely overlook
SymbolLookup altogether. I'll think about this (we did some back and
forth on this, also related to the naming of methods in the CLinker
class itself, which are now resolved).
As to why we have multiple ways to lookup symbols (e.g. compared to
Python) the reason is that Panama is not the first mechanism to
introduce a concept of library loading in the JDK. Before Panama there
was JNI - with its own library loading mechanics. The methods in (1)
allow an application written using JNI loading mechanism to migrate to
use the CLinker instead. Of course if you are writing code from scatch,
and just need a dlopen replacement in Java, you should just look at (2).
Maurizio
On 26/04/2022 11:39, Jack Andrews wrote:
> hi - i'm getting used to FFI in JDK 18. any help with the following problem
> is much appreciated.
>
> I have a C function `kinit` in libk.so:
> $ nm -D ./libk.so |grep kinit
> 00000000000296f0 T kinit
>
> $ java --version
> openjdk 18.0.1 2022-04-19
> OpenJDK Runtime Environment (build 18.0.1+10-24)
> OpenJDK 64-Bit Server VM (build 18.0.1+10-24, mixed mode, sharing)
>
> $ cat Example.java
> import jdk.incubator.foreign.*;
> import java.lang.invoke.*;
> import static jdk.incubator.foreign.ValueLayout.*;
>
> public class Example {
>
> static CLinker LINKER = CLinker.systemCLinker();
>
> public static void main(String[] args) throws Throwable {
> System.loadLibrary("k");
> kinit();
> }
>
> public static void kinit() throws Throwable {
> MethodHandle kinit = LINKER.downcallHandle(
> /* LINE 16 */ LINKER.lookup("kinit").get(),
> FunctionDescriptor.of(JAVA_INT)
> );
>
> {
> int r = (int) kinit.invoke();
> System.out.println(r);
> }
> }
> }
>
> my code appears to load libk.so, but fails to find kinit:
>
> $ LD_LIBRARY_PATH=. java --add-modules jdk.incubator.foreign
> --enable-native-access=ALL-UNNAMED Example.java
> WARNING: Using incubator modules: jdk.incubator.foreign
> warning: using incubating module(s): jdk.incubator.foreign
> 1 warning
> Exception in thread "main" java.util.NoSuchElementException: No value
> present
> at java.base/java.util.Optional.get(Optional.java:143)
> at Example.kinit(Example.java:16)
> at Example.main(Example.java:11)
>
> best,
> jack
More information about the panama-dev
mailing list