BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News JNA brings native code to JRuby

JNA brings native code to JRuby

This item in japanese

One of JRuby's problems might soon get a solution: POSIX support integration and native extension support. POSIX stands for Portable Operating System Interface, and is a group of standards. Among other things, it provides APIs for filesystem access or networking. This allows for tighter OS integration, or at least as tight as the POSIX integration of the OS.

Until now, supporting POSIX calls was quite difficult with JRuby. Using equivalent Java APIs is one way to go, but even if  a Java equivalent of the functionality exists, it might not have the right semantics. And if the Java platform lacks the functionality, there remain only workarounds like launching command line programs to do the tasks.

Charles Nutter of the JRuby team reports the native code and POSIX on his blog:
I know, I know. It's got native code in it, and that's bad. It's using JNI, and that's bad. But damn, for the life of me I couldn't see enough negatives to using Java Native Access that would outweigh the incredible positives. For example, the new POSIX interface I just committed:

import com.sun.jna.Library;
public interface POSIX extends Library {
   public int chmod(String filename, int mode);
   public int chown(String filename, int owner, int group);
}
The (not so) secret ingredient here is the Java Native Access (JNA) library, not to be confused with Java's JNI. While JNI provides access to native C code, it requires extra effort and glue code, such as JNI header definitions that need to be compiled, to access it.

For the given example, this code using JNA is all that's needed to load and access the library:
import com.sun.jna.Native
POSIX posix = (POSIX)Native.loadLibrary("c", POSIX.class);
This loads the standard C library, and gives access to chmod (for changing file access permissions) and chown (changing the owner of a file) functions. Of course, this approach is not limited to these two functions. Adding further functions to the POSIX interface from the code sample would allow access to ever more functions of C stdlib. After all, Native.loadLibrary simply tries to map the names from the Java interface methods to C functions in the library and make them accessible.

JNA still uses JNI under the covers to access libffi which does all the magic. Using JNI brings along problems, for instance it's possible to run afoul of security managers that might not allow it or get into  trouble with JEE containers.
Obviously, whenever native libraries are shipped, they need to fit the platform. The currently available JNA release ships with libraries compiled for Win32, Linux 32 and 64 bit x86 versions, Solaris SPARC and x86, FreeBSD, and Darwin (MacOS X) for PPC and x86, which covers quite a lot of the available spectrum.

Easy access to native libraries from JRuby is useful, but JNA opens another possibility: support for Ruby native extensions. These are shared libraries that are loaded in a Ruby process and can access the internals of the Ruby interpreter. Native extensions are widely used. For instance, the popular rcov tool, used to determine the test coverage of a piece of code, makes use of the Ruby API to see which code is actually executed in a test run.

Support for this is not as easy as the examples above, as it requires a full implementation of the Ruby C Language API that extensions use to interact with the Ruby runtime. This is a two way affair: native code can call this API, but the Ruby runtime also invokes callbacks for certain events.  For more details on native extensions, see the Extending Ruby chapter of the online version of Programming Ruby.

Is the lack of POSIX functionality in JRuby a problem for you? What native extensions do you miss in JRuby?

Rate this Article

Adoption
Style

BT