Using SymbolLookup#libraryLookup with fallback of SymbolLookup#loaderLookup
some-java-user-99206970363698485155 at vodafonemail.de
some-java-user-99206970363698485155 at vodafonemail.de
Mon Oct 7 23:08:20 UTC 2024
Thanks a lot for both your answers! Yes Maurizio you are right, I was
asking this in the context of tree-sitter / jtreesitter ;)
However, I think this generally applies to all native libraries which
want to provide 'official' Java bindings through the foreign API, for
example also database drivers or similar.
> A user can simply amend the OS dependent library search locations.
> Typically through amending PATH (Windows), LD_LIBRARY_PATH (Linux), or
> DYLD_LIBRARY_PATH (mac), but there are other options. This will work
> for a library's dependencies as well, and is more or less as much
> effort as setting java.library.path, I think?
I think this is part of the problem: If you are maintaining Java
bindings for native libraries, and maybe even provide prebuilt binaries
for certain targets, then users can't just place the native libraries at
one place. Instead you need to tell your users to lookup where their OS
loads libraries from (and possibly you cannot assist because you are not
familiar with their OS). And similarly if users want to write a start or
install script for their application, they can't just copy the library
to a fixed location, instead they need to write OS specific code (and
possibly even code for detection of the OS) to place the libraries at
the correct location respectively adjust the correct environment
variable. This can be cumbersome to users who are not very familiar with
native development.
And it can lead to situations similar to "works on my machine", for
example: You develop on Windows and place the Windows native library in
the working directory (= included in PATH) and it works, then you try to
set up CI on Linux but placing the Linux native library in the working
directory does not work (because the working directory is not included
in LD_LIBRARY_PATH by default).
Maybe this can be solved by using a different `--library` option of
jextract, but it might not be obvious what the correct / best choice for
binding authors is.
>> Ideally this would be solved with a user-provided SymbolLookup (see
>> also [1] and CODETOOLS-7903186), but that might not be that easily
>> achievable or complicate the API of jextract-based bindings.
> Yes, this is the general solution to this kind of problems.
My concern here is that this mostly works for bindings which expose
native methods as static Java methods, e.g. OpenGL [^1]. However, for
bindings such as jtreesitter this might require larger API changes
because it currently uses constructors to create binding objects (e.g.
`new Parser(...)`). If jextract supported providing a custom
SymbolLookup, then it would require a factory class and factory methods
which use that lookup, e.g. `var jtreesitter = new
JTreesitter(symbolLookup); var parser = jtressitter.newParser(...)`.
That might be the cleanest approach but would require some (larger)
refactoring for existing code.
An alternative might be a `static volatile SymbolLookup` field which is
lazily initialized and can be overwritten (but only if not overwritten /
initialized yet).
These are just some of my thoughts on this. As mentioned in the other
thread, I am only a user of jtreesitter and am not directly writing Java
bindings using the foreign API.
I am also not sure what the best solution here would be, maybe other
users will come up with better solutions over time and highlight
different aspects of this, or it would be worth having a look at how
other projects using the foreign API currently solve this.
> I want to point out another issue with
> System::load(Library)/java.library.path. It doesn't handle library
> dependencies, which are instead handled automatically by the OS loader.
Good point, this will probably lead to confusing 'surprises' in some
cases. I had created JDK-8339367 to make it clearer how
`java.library.path` works and where it has an effect.
Though if authors of bindings know that their library has no specific
dependencies, then maybe at least in these cases this is not an issue.
> [The proposal to ignore the exception and use loaderLookup as
> fallback] would allow jextract to “keep going” even in the face of
> library loading errors. My question is whether this behavior would be
> useful
Also good point, yes that might make troubleshooting more difficult,
especially if the library file exists but could not be loaded for
another reason. And it would not be as clear anymore where a symbol was
actually loaded from.
Kind regards
[^1]: Similar to what you Maurizio mentioned previously with
```
final static OpenGL GL = new OpenGL(mylookup);
GL.glVersion();
```
More information about the jextract-dev
mailing list