Also the difference between using .NET's P/Invoke (DllImport) interface versus Java's JNI is about as big as can be in terms of developer pain and overhead.
Have a look at JNA. It's about as easy to use as P/Invoke.
Of course Java's days on the desktop are kind of numbered with the various browser and OS vendors getting visibly concerned about the security of the JRE, but that's a different matter.
Unfortunately it's still a huge pain to use JNA with stuff that returns unions (or a pointer to different type depending on the usage context). That makes things like X libraries wrappers really difficult to write in a clean way.
Of course Java's days on the desktop are kind of numbered with the various browser and OS vendors getting visibly concerned about the security of the JRE, but that's a different matter.