Cannot link Java class com.sun.jna.NativeLibrary (NameError)

This isn’t directly an issue with JRuby, but I’m going to post here
since I ran into this issue using JNA through JRuby(so easy) and I
just want to get this out there in the hopes it will save somebody
some time.

I had a requirement to write a syslog entry from a JRuby/Rails app.
JNA worked nicely, but when running our tests on the ‘build’ machine
things bombed out.

Simple case:

jruby -e “Java::com.sun.jna.NativeLibrary.getInstance(‘c’)”
-e:1:in `method_missing’: cannot link Java class
com.sun.jna.NativeLibrary (NameError)
from -e:1

To isolate from JRuby I compiled and ran a copy of the HelloWorld JNA
example from the JNA home page and got the following.

java version “1.5.0_12”

java -cp $JRUBY_HOME/lib/jruby-complete.jar:. HelloJNA
Exception in thread “main” java.lang.UnsatisfiedLinkError: /tmp/
jna2366.tmp: Can’t load IA 32-bit .so on a IA 32-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1647)
at java.lang.Runtime.load0(Runtime.java:769)
at java.lang.System.load(System.java:968)
at com.sun.jna.Native.loadNativeLibrary(Native.java:507)
at com.sun.jna.Native.(Native.java:89)
at HelloJNA$CLibrary.(HelloJNA.java:7)
at HelloJNA.main(HelloJNA.java:15)

After some googling on this it seemed that the JVM version had a bug
that was hiding the true exception so I tried with 1.6 and got:

java version “1.6.0_02”

java -cp $JRUBY_HOME/lib/jruby-complete.jar:. HelloJNA
Exception in thread “main” java.lang.UnsatisfiedLinkError: /tmp/
jna1781.tmp: /tmp/jna1781.tmp: failed to map segment from shared
object: Operation not permitted
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1647)
at java.lang.Runtime.load0(Runtime.java:770)
at java.lang.System.load(System.java:1005)
at com.sun.jna.Native.loadNativeLibrary(Native.java:507)
at com.sun.jna.Native.(Native.java:89)
at HelloJNA$CLibrary.(HelloJNA.java:7)
at HelloJNA.main(HelloJNA.java:15)

Which eventually led me to the root of the problem which was that the
build machine had /tmp mounted noexec and JNA needs to write temp
files with executable perms. After all this grief, all that was
needed was to set java.io.tmpdir suitably.

jruby -J-Djava.io.tmpdir=. -e
“Java::com.sun.jna.NativeLibrary.getInstance(‘c’)”

Also, I initially tried to set java.io.tmpdir when running our tests
from rake and ran into a small setback with that. See: ‘invoking
jruby from jruby with -J option’

http://archive.jruby.codehaus.org/user/ADF94981-F26D-4B05-
BC61-306D53E9608C%40aps.org

-lenny