Support request about FFM Panama Implementation

roberto.minoletti at trusthub.cloud roberto.minoletti at trusthub.cloud
Wed Feb 5 15:59:06 UTC 2025


Thank you Jorn to adise us about it.
      Yes definitively our requirement is to instantiate the same library (or many virtual instances of the same library) but with different configurations, parameters, settings and a dedicated memory allocation for each user where to store specific datas for each proces.

So, following your suggestion and going for the option 1 (1. implementing a custom library loader….) is it something that we should resolve in our Java Code or we should work on the OS side? Have you got some sample code or any open Source Project to do that or any suggestion to hemp us to approach this point correctly?

Using for example a “ofConfined” ARENA, when a tread is ended then the library is automatically removed both from the process and from the memory or just from the process?

Referring to your sample code, moreover to empty the memorySegment x1, x2 does Panama remove also the values from X?
Además de vaciar el memoryegment vacia ambien los valores donde están los valores?
And does it remove it also from the cache?

Thank you in advance
Roberto


De: Jorn Vernee <jorn.vernee at oracle.com> 
Enviado el: miércoles, 5 de febrero de 2025 11:16
Para: Maurizio Cimadamore <maurizio.cimadamore at oracle.com>; roberto.minoletti at trusthub.cloud; panama-dev at openjdk.org
Asunto: Re: Support request about FFI Panama Implementation

I want to caution a bit that, while the FFM API does allow loading the same library in multiple class loaders, the underlying OS library loader will _not_ load the same library twice, but instead keeps a reference count for each library, and increments it when it is loaded (again), and decrements it when it is unload. This can be demonstrated with the following example:
lib.c:
    int x;
Main.java:

    SymbolLookup s1 = SymbolLookup.libraryLookup("lib.so", Arena.global());
    MemorySegment x1 = s1.findOrThrow("x")
            .reinterpret(ValueLayout.JAVA_INT.byteSize());
    SymbolLookup s2 = SymbolLookup.libraryLookup("lib.so", Arena.global());
    MemorySegment x2 = s2.findOrThrow("x")
            .reinterpret(ValueLayout.JAVA_INT.byteSize());
        
    x1.set(ValueLayout.JAVA_INT, 0L, 42);
    System.out.println(x2.get(ValueLayout.JAVA_INT, 0L));
This program will print '42'. Note that this is a limitation of the operating system's library loader, combined with how the library is implemented.
> The goal is that each object/tread parallely instantiate the same library but having isolated states, configurations and variables stored in a dedicated memory slot for each tread, so even if the C++ library maybe does not completely support cuncurrency itself it should attend multiple treads as it is virtually responding at once having one specific configuration per user.
In other words, what you seem to want here is not possible without either: 1. implementing a custom library loader that creates separate instances of the library in memory, or 2. changing the library so that each client can have a separate library state (this is typically done by the library returning some kind of 'handle', and then that handle is used in subsequent operations).
Jorn
On 5-2-2025 10:50, Maurizio Cimadamore wrote:
Hi Roberto,
by "singleton limitation" in JNA, I assume you refer to the fact that, in JNA (but also JNI) you can only load a native library once, by only one classloader. Correct?
If that's the limitation you are trying to workaround, then yes, FFM allows you to load the same native library multiple times using its SymbolLookup abstraction. Make sure to use the correct factory -- the one that does not rely on an association with the current classloader:
https://docs.oracle.com/en/java/javase/23/docs//api/java.base/java/lang/foreign/SymbolLookup.html#libraryLookup(java.lang.String,java.lang.foreign.Arena)
This is just a very thin wrapper around dlopen, so it will take whatever library name dlopen can resolve, and will also allow you to open the library multiple times. Note that the library will be unloaded when the provided arena is closed -- so ideally you could use one arena per client.
Examples of Arena.ofConfined, or custom arenas can be found in the javadoc:
* confined arena - https://docs.oracle.com/en/java/javase/23/docs//api/java.base/java/lang/foreign/package-summary.html
* custom arena - https://docs.oracle.com/en/java/javase/22/docs//api/java.base/java/lang/foreign/SymbolLookup.html#libraryLookup(java.lang.String,java.lang.foreign.Arena)
We also have some narrative documents on how to use memory segment and linker API here:
https://github.com/openjdk/panama-foreign/blob/foreign-memaccess%2Babi/doc/panama_memaccess.md
https://github.com/openjdk/panama-foreign/blob/foreign-memaccess%2Babi/doc/panama_ffi.md
And, if you want to know more on jextract, we have a comprehensive guide here:
https://github.com/openjdk/jextract/blob/master/doc/GUIDE.md

Cheers
Maurizio
On 05/02/2025 00:03, mailto:roberto.minoletti at trusthub.cloud wrote:
Hello Maurizio,
      Thank you to provide the right contact of the Panama project (I reached to you in LinkedIn some days ago)
I am writing to you on behalf of a backend development team that is trying to accomplish our requirements.
 
We need to interact from our java code (JDK21 that we can easely update to JDK23 if required and Spring Web-Flux) to a C++ library that allow to create Slots, generate Keypairs store Certificates simulating a real HSM (Hardware Security Module). This is named libsofthsm2.so (SoftHSM2).
As I mentioned we customized this library as we need to store certificates and keys in a different path for each user. One important requirement is that we need to be able to process many requests coming from many different users to the same library that should operate in different paths at the same time.
We preliminary resolved a POC using JNA but when tried to execute many parallel treads we faced with his singleton limitation and after a deep reasearch we founded Panama project.
 
Does Panama FFI support multiple parallel treads? Does it have any Singleton limitations?
What we need is to get many objects/treads at the same time (paralley) loading its own different instance of the same library, getting its own memory context, variables and states, all completely isolated but working at the same time. This was not possible for us because JNA uses the Singleton pattern to load the library directly into the process, making it only possible to have a single instance of the library for the entire process.
 
The goal is that each object/tread parallely instantiate the same library but having isolated states, configurations and variables stored in a dedicated memory slot for each tread, so even if the C++ library maybe does not completely support cuncurrency itself it should attend multiple treads as it is virtually responding at once having one specific configuration per user.
 
What we are looking for is that each ARENA has access to libsofthsm2.so and its internal variables using that dedicated memory space to each tread to calculate the operations it must perform.
 
Does Panama FFI allow all this? This is the first basic question we have. After this we will be able to perform more specific questions.
Also if you have any sample of code that use Arena.ofConfined() or any Custom Arena it would be really fantastic.
 
Thank you in advance for any information and/or support impelmenting Panama in our Project.
 
Roberto Minoletti
Trusthub LLC



More information about the panama-dev mailing list