JNI UnsatisfiedLinkError

P

protoplasm

I've followed Sun's "The Java Native Interface" by Sheng Liang on
creating a JNI test/example. Unfortunately it isn't working for me.
This leads me to believe that either I'm doing something stupid or
things have changed in later versions of Java.

Environment information:
$ java -version
java version "1.4.2_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_16-b05)
Java HotSpot(TM) Client VM (build 1.4.2_16-b05, mixed mode)
$ cat /etc/SuSE-release
SUSE LINUX Enterprise Server 9 (x86_64)
VERSION = 9
PATCHLEVEL = 3
$ gcc --version
gcc (GCC) 3.3.3 (SuSE Linux)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
$ uname -a
Linux cressida 2.6.5-7.287.3-default #1 Tue Oct 2 07:31:36 UTC 2007
x86_64 x86_64 x86_64 GNU/Linux

The below source code is taken directly from the book. Here is my
HelloWorld.java file:

class HelloWorld {
private native void print();
public static void main(String[] args) {
new HelloWorld().print();
}
static {
System.loadLibrary("HelloWorld");
}
}

Here is the HelloWorld.c file:

#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}

Steps to build:

$ javac HelloWorld.java
$ javah -jni HelloWorld
$ gcc -O2 -fPIC -pthread -W -Wall -Wno-unused -Wno-parentheses -pipe -
D_LARGEFILE64_SOURCE -D_GNU_SOURCE -D_REENTRANT -D_LITTLE_ENDIAN -
D_LP64=1 -c HelloWorld.c
$ gcc -z defs -Wl,-O1 -Wl,-soname=libHelloWorld.so -static-libgcc -
shared -mimpure-text -o libHelloWorld.so -lc

Run the Java app:

$ java -Djava.library.path=. HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/
sprotsman/workspace/HelloWorldJ2/libHelloWorld.so: /home/sprotsman/
workspace/HelloWorldJ2/libHelloWorld.so: cannot open shared object
file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1586)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1511)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:834)
at HelloWorld.<clinit>(HelloWorld.java:7)

Any help on what I'm doing wrong would be much appreciated.

--Shawn
 
P

protoplasm

This implies you have a module called HelloWorld.so on the path.
Seehttp://mindprod.com/jgloss/jni.htmlhttp://mindprod.com/jgloss/runerrormessages.html#UNSATISFIEDLINKERROR

Hi Roedy,

Yes, HelloWorld.so is in my current working dir:

/home/sprotsman/workspace/HelloWorldJ2/
$ ls
HelloWorld.c HelloWorld.class HelloWorld.h HelloWorld.java
libHelloWorld.so
 
G

Gordon Beaton

This implies you have a module called HelloWorld.so on the path.

No, on two counts.

It assumes that the file is called libHelloWorld.so, and that it's in
java.library.path or LD_LIBRARY_PATH or in a "standard place" like
/lib or /usr/lib (see "man ld.so"). Linux does not use PATH to find
libraries.

/gordon

--
 
G

Gordon Beaton

Yes, HelloWorld.so is in my current working dir:

/home/sprotsman/workspace/HelloWorldJ2/
$ ls
HelloWorld.c HelloWorld.class HelloWorld.h HelloWorld.java
libHelloWorld.so

But is your working dir in either java.library.path or
LD_LIBRARY_PATH?

Does "file libHelloWorld.so" correctly identify the file as a shared
object?

Is every additional dependency (as reported by "ldd libHelloWorld.so")
reachable by LD_LIBRARY_PATH or in standard places where ld.so can
find them, such as /lib, /usr/lib or other directories mentioned in
/etc/ld.so.conf?

/gordon

--
 
P

protoplasm

Does "file libHelloWorld.so" correctly identify the file as a shared
object?

Is every additional dependency (as reported by "ldd libHelloWorld.so")
reachable by LD_LIBRARY_PATH or in standard places where ld.so can
find them, such as /lib, /usr/lib or other directories mentioned in
/etc/ld.so.conf?

I went ahead and tried out the example on Roedy's site (mindprod).
Sadly, the results were the same. Here is every step:

sprotsman@cressida:~/workspace> mkdir -p Glue/com/mindprod/JNIexper
sprotsman@cressida:~/workspace> cd Glue

Copy Java source from web page and inserted into Glue/com/mindprod/
JNIexper/Glue.java.

sprotsman@cressida:~/workspace/Glue> javac -classpath . com/mindprod/
JNIexper/Glue.java

sprotsman@cressida:~/workspace/Glue> javah -jni -o Glue.h
com.mindprod.JNIexper.Glue

Copy C source from web page and inserted into Glue/Glue.c. Changed
"#include <windows.h>" to "#include <stdio.h>".

sprotsman@cressida:~/workspace/Glue> gcc -fPIC -D_REENTRANT -I/usr/lib/
SunJava2-1.4.2/include -I/usr/lib/SunJava2-1.4.2/include/linux -c
Glue.c

sprotsman@cressida:~/workspace/Glue> gcc -shared Glue.o -o
libGlue.sosprotsman@cressida:~/workspace/Glue> java -classpath .
com.mindprod.JNIexper.Glue

sprotsman@cressida:~/workspace/Glue> java -Djava.library.path=. -
classpath . com.mindprod.JNIexper.Glue
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/
sprotsman/workspace/Glue/libGlue.so: /home/sprotsman/workspace/Glue/
libGlue.so: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1586)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1511)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:834)
at com.mindprod.JNIexper.Glue.<clinit>(Glue.java:10)

To answer Gordon's questions:

Contents of current working directory:

sprotsman@cressida:~/workspace/Glue> ls -F
com/ Glue.c Glue.h Glue.o libGlue.so

sprotsman@cressida:~/workspace/Glue> ldd libGlue.so
libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9567c000)
/lib64/ld-linux-x86-64.so.2 (0x000000552aaaa000)

sprotsman@cressida:~/workspace/Glue> file libGlue.so
libGlue.so: ELF 64-bit LSB shared object, AMD x86-64, version 1
(SYSV), not stripped
 
G

Gordon Beaton

To answer Gordon's questions:

Contents of current working directory:

sprotsman@cressida:~/workspace/Glue> ls -F
com/ Glue.c Glue.h Glue.o libGlue.so

sprotsman@cressida:~/workspace/Glue> ldd libGlue.so
libc.so.6 => /lib64/tls/libc.so.6 (0x0000002a9567c000)
/lib64/ld-linux-x86-64.so.2 (0x000000552aaaa000)

sprotsman@cressida:~/workspace/Glue> file libGlue.so
libGlue.so: ELF 64-bit LSB shared object, AMD x86-64, version 1
(SYSV), not stripped

You didn't answer the most important question: is your working
directory part of LD_LIBRARY_PATH, or java.library.path?

I see you've built a 64-bit library. Are you using a 64-bit JVM?

What happens when you use
System.load("/complete/path/to/libHelloWorld.so");
instead of
System.loadLibrary("HelloWorld")?

/gordon

--
 
J

joerg

...

sprotsman@cressida:~/workspace/Glue> file libGlue.so
libGlue.so: ELF 64-bit LSB shared object, AMD x86-64, version 1
(SYSV), not stripped

Just a guess:

We had similar problems on other platforms when trying to
use 64-bit libraries with 32-bit java/jvm binaries or vice versa.

I don't know if this could happen also in your environment, but it's
worth a try. (Can 64-bit Linux run 32-bit programs on AMD?)

Joerg
 
N

Nigel Wade

joerg said:
Just a guess:

We had similar problems on other platforms when trying to
use 64-bit libraries with 32-bit java/jvm binaries or vice versa.

I don't know if this could happen also in your environment, but it's
worth a try. (Can 64-bit Linux run 32-bit programs on AMD?)

Yes, but you cannot mix them - a 32bit application cannot load a 64bit library,
and vice versa.

Although I have heard there is a mechanism which allows a 64bit Firefox to load
the 32bit Java and Swing plugins, so that might not be entirely accurate.
 
P

protoplasm

Nigel, joerg,

That came to mind too. I tried compiling the libHelloWorld.so with -
m32 and that seems to have done the trick.

$ gcc -m32 -fPIC -D_REENTRANT -I/usr/lib/SunJava2-1.4.2/include -I/usr/
lib/SunJava2-1.4.2/include/linux -c HelloWorld.c
$ gcc -m32 -shared HelloWorld.o -o libHelloWorld.so

Running the Java app:

$ java -Djava.library.path=. HelloWorld
Hello World!

Yay!
 
R

Roedy Green

I went ahead and tried out the example on Roedy's site (mindprod).
Sadly, the results were the same. Here is every step:

the example on my site is for windows.

Use Wassup to find out what directories it is scanning for *.so native
code.

see http://mindprod.com/applet/wassup.html

look in the restricted properties for:

java.library.path = F:\Program Files\Opera 9.5
beta;.;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;E:\ENV;E:\SYS;C:\Windows;C:\Windows\SYSTEM32;C:\Windows\SYSTEM32\WBEM;F:\program
files\jet5.0-pro\bin;F:\program
files\jpsoft\4NT8;E:\apache-ant-1.7.0\bin\;E:\vslick\win;E:\Program
Files\Java\jdk1.6.0_03\bin;C:\Program Files\QuickTime\QTSystem\

These are all the places it will look. The current directory is not
necessarily in that list, though in my case it is.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,150
Members
46,697
Latest member
AugustNabo

Latest Threads

Top