Classes using native CNI methods are loaded without any extra security checks. When a class uses native JNI methods it needs to make sure the appropriate library containing the JNI functions are loaded. Which means that at a certain point the call chain must have had a RuntimePermission("loadLibrary") because Runtime.loadLibrary() has to be called. For classes using CNI native methods no such requirement is needed which means that "CNI native code" can be called through such classes without a security check for the RuntimePermission being done. A "solution" could be to have the static initializer of such classes using CNI native code make a security check themselves for RuntimePermission("loadLibrary"). This does mean we need some way to simulate the "trusted" way of calling Runtime.loadLibrary() through a PrivilegedAction (which means the class itself needs to have the RuntimePermission, but the rest of the call chain doesn't).
Confirmed.
I'm not sure that this should really be considered a bug. loadLibrary() must obviously be a privileged function because arbritary code could be loaded by calling it (possibly from an insecure context), but having/calling a CNI method does not in itself cause anything to be loaded. A CNI method implementation must already be loaded by being explicitly linked into an application binary. To put it another way: is there a way that insecure bytecode can actually turn this into an exploit? Perhaps some kind of validity check is needed at link time to ensure that native method declarations in insecure code do not link against an inappropriate native method (for example, make sure that insecure classes cannot call themselves gnu.foo.Whatever and get linked to a private CNI method implementation in another class of the same name). In any case, checking the loadLibrary permission is the wrong approach because there is no library actually being loaded. The correct behaviour would be to simply not link the method if something isn't right, resulting in an UnsatisfiedLinkError.
Closing as won't fix as libgcj (and the java front-end) has been removed from the trunk.