I've worked with a lot of FFIs (starting with Common Lisp in the '80s), and I've written a few, such as:
https://blogs.oracle.com/jrose/resource/esh/RoseMullerIX.html
That said, I think JNR is the best such thing yet for Java. The libffi under it is amazingly portable. Charlie's presentation at the JVM Language Summit was compelling.
So JNR makes an unusually good starting point for a standards discussion.
I also think there are ways to improve JNR to make it even more useful. (For its natural use cases, putting that question aside for the moment.)
Here is a brief four-point sketch of possible areas for adjustment.
A. [layering] Clearly distinguish three APIs: The end-user API, the metadata API, and the JVM-facing API. (Currently, metadata is "interpretively" entangled with at least some end-user objects, such as data structs.)
The JVM-facing API is the peeks and pokes; Unsafe is designed to be this (the jffi is within epsilon of the missing bit there).
The metadata API should do most of its work before making a single native call or data access. (More later.)
The end-user API should be easy to use from Java code, wrappable, reasonably well typed, etc., etc.
B. [interfaces] Use interfaces for data as well as functions. (Current JNR uses concrete classes.)
By abstracting data accesses we can do various useful games, such as redirecting accesses to other processes or core files. We can also wrap big invariants around data accesses, such as "allow safepoints here but only if managed pointers are handle-ized".
C. [metadata] Generate metadata, for both functions and data, from a header file scanner. Run the user layer from this metadata, not from classes the user wrote to ape the contents of a C header file.
libclang appears to be an ideal starting point for the frontend. (I did it once with yacc, and Ken Russell and I did it once with swig. Having a real front end would be refreshing.)
D. [optimizability] Calls and data structure accesses from Java should JIT-compile to about the same code as the C compiler emits for it's own accesses.
Getting the layering right will make this possible. The metadata has to be something "static" that the JIT can consult while it processes native access points in Java code. The JVM-facing API (Unsafe+jffi) has to be built from metadata driven intrinsics that the compiler can fold up to C-like code.
This is presently the case for Unsafe-based data accesses, but getting the JIT to understand the jffi view of things will be tricky, because of the "interpretive" orientation of the jffi/libffi stuff.
Big cheers,
— John