RFE: support safely wrapping restricted FFM calls

Kasper Nielsen kasperni at gmail.com
Sat Nov 18 05:46:56 UTC 2023


Hi Rob,

Delegating caller sensitive methods can be tricky.

Besides the obvious solutions with StackWalker and/or Lookup objects I've
sometimes used an abstract class that must be extended by users of my library.
This may be more trouble in your case than the other solutions though.

In your situation it would be something like this.

// Defined in your library and extendable by users of your library
public abstract class NativeLoader {

    protected abstract MethodHandle downcallHandle(Linker linker, MemorySegment
         address, FunctionDescriptor function, Linker.Option... options);

    public final <T> T load(Class<T> interFace) {
     .. do stuff.
     call this.downcallHandle
     .. do more stuff
    }
}

// Usage by other library
class UsageByOtherLibrary {
   private static final NativeLoader NL = new NativeLoader() {
        protected MethodHandle downcallHandle(Linker linker, MemorySegment
                   address, FunctionDescriptor function, Option... options) {
            return linker.downcallHandle(address, function, options);
        }
    };

    public void main() {
        SomeInterface si = NL.load(SomeInterface.class);
    }
}

The actual call to Linker.downcallHandle is now only performed by the user of
your library. So depending on what you do, you might even be able to avoid
requiring enabling native access for your library. Only the libraries that use
your library would need it.

/Kasper




On Thu, 16 Nov 2023 at 19:21, Rob Spoor <openjdk at icemanx.nl> wrote:
>
> On 16/11/2023 18:15, Maurizio Cimadamore wrote:
> >
> > On 16/11/2023 16:54, Rob Spoor wrote:
> >> Hi Maurizio,
> >>
> >> I don't think you understand what my module is doing. For instance,
> >> it's not specifying the downcall method handles themselves, it's just
> >> making it easy to define them. Maybe a small example would show what
> >> I'm doing.
> >>
> >> Consider the following partial interface from JNA:
> >>
> >>     public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {
> >>
> >>         /** The instance. */
> >>         Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class,
> >> W32APIOptions.DEFAULT_OPTIONS);
> >>
> >>         int GetLastError();
> >>     }
> >>
> >> What JNA is doing is creating an implementation based on this
> >> interface that delegates to the native kernel32 library. This is all
> >> done through the Native.load method.


More information about the core-libs-dev mailing list