, BitFlipper wrote

I think the reason there is such a day/night difference between PInvoke and JNI is that when MS released .Net, they knew it lacked a lot of functionality that Win32 provided, so they simply had to make this stuff work properly. Java doesn't sit on top of a legacy C API and therefore JNI is just an afterthought.

I think it's more that Java was designed with the pipe dream of true cross-platform functionality. Being able to call into platform-dependent native libraries is contrary to that goal. By contrast, .Net was primarily designed to only run on Windows; sure the core ECMA CLI is platform independent but that was never the main goal.