InfoQ

InfoQ

News

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

JNA brings native code to JRuby

Posted by Werner Schuster on Sep 05, 2007

Sections
Development,
Architecture & Design
Topics
Java ,
Ruby ,
Programming ,
JRuby
Tags
JRuby
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?
JNI required by JNA? by Chris Morris Posted
Re: JNI required by JNA? by Werner Schuster Posted
  1. Back to top

    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?

  2. Back to top

    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.

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.