Regarding seamless FFI, I suspect that part of the JNI friction was intentional, out of fear that programmers would use FFI as a crutch.
Erlang's BEAM's nif[0] interface is the best I've seen in mainstream runtimes for FFI. You write an Erlang/Elixir/etc. function, and loading a native library may swap out the function body. This allows for workarounds in Erlang/Elixir/etc. in case of version skew in your native libraries.
In my day job, I work with a domain-specific language with a similar FFI (actually, 3 different FFIs, one similar to nifs), and it's very handy to have a fallback that does things with /proc/, calling external command line binaries, slower versions of FFI functions, etc. (This allows the native code release schedule to be decoupled from the domain-specific language code changes.)
The syntax isn't the same, but a Java-like syntax would be
// getpid is built in, but it could be done something like this
// look for XNativeGetPID() in mylib.so or mylib.dll depending on OS
@native_replace("XNativeGetPID", "mylib")
public static int getpid() {
// Throw an exception if you want to force
// native implemementation
return Integer.parse(Runtime.system( "/bin/grep pid /proc/self/status | /bin/sed 's/..." ));
}
[0]
http://erlang.org/doc/man/erl_nif.html