JNA brings native code to JRuby

| by Werner Schuster on Sep 05, 2007. Estimated reading time: 3 minutes |
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


Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

JNI required by JNA? by Chris Morris

Your article says, "JNA still uses JNI under the covers", but the jna home page says, "no JNI or native code is required". Are these statements compatible - does the JNA homepage mean only that JNI is not required in my code?

Re: JNI required by JNA? by Werner Schuster

JNA uses JNI to access libffi. I can't speak for the JNA guys, but I guess the "no JNI or native code required" means that, if you use JNA, you don't have to use JNI, instead you only use the JNA API calls and they do all the nasty JNI stuff in the background. One big problem with JNI is that if you want to access native code, you need to write a C library that needs to include JNI headers and compile and ship it with your product. This C library's functions area all you can call - nothing else. It's not possible to just load any old DLL or shared lib with plain JNI - JNA, on the other hand, can just take a DLL or shared lib, figure out what it provides and make these calls available.
Also: look into the jna.jar (that you can download at the JNA site) - it ships with native libs for various platforms.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

2 Discuss