Java Forum / General / November 2007
JNI Programming
Bala - 06 Nov 2007 17:29 GMT Hello,
I am programming using JNI to call a method from a c static library. I created the shared library for this purpose and the necessary compilations.
Now, when i try to run my application Main.java, it gives me the following runtime error
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home1/ users/biyer/Bala/OAPI/src/libOpenApiImp.so: Can't load Sparc 32-bit .so on a Sparc 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:1676) at java.lang.Runtime.loadLibrary0(Runtime.java:822) at java.lang.System.loadLibrary(System.java:993) at OpenApi.<clinit>(OpenApi.java:7) at Main.main(Main.java:5)
I am using the following version of JAVA on Solaris 10 Sparc
java version "1.5.0_12" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04) Java HotSpot(TM) Server VM (build 1.5.0_12-b04, mixed mode)
Please let me know whats going wrong?
Gordon Beaton - 06 Nov 2007 17:33 GMT > Exception in thread "main" java.lang.UnsatisfiedLinkError: /home1/ > users/biyer/Bala/OAPI/src/libOpenApiImp.so: > Can't load Sparc 32-bit .so on a Sparc 32-bit platform Well that is an odd message...
What commands did you use to build the .so file?
What do "file libOpenApiImp.so" and "ldd libOpenApiImp.so" say?
/gordon
--
Bala - 06 Nov 2007 18:20 GMT > > Exception in thread "main" java.lang.UnsatisfiedLinkError: /home1/ > > users/biyer/Bala/OAPI/src/libOpenApiImp.so: [quoted text clipped - 9 lines] > > -- Hello,
I built the .so using the following command g++ -Wno-deprecated -G -I/usr/java/include -I/usr/java/include/solaris -I/home1/users/biyer/Bala/OAPI/include JavaC.C -o libOpenApiImp.so
This is what ldd says ldd libOpenApiImp.so libstdc++.so.6 => /usr/sfw/lib/libstdc++.so.6 libm.so.2 => /lib/libm.so.2 libgcc_s.so.1 => /usr/sfw/lib/libgcc_s.so.1 libc.so.1 => /lib/libc.so.1 /platform/SUNW,Sun-Fire-480R/lib/libc_psr.so.1
Gordon Beaton - 06 Nov 2007 18:52 GMT > I built the .so using the following command > g++ -Wno-deprecated -G -I/usr/java/include > -I/usr/java/include/solaris -I/home1/users/biyer/Bala/OAPI/include > JavaC.C -o libOpenApiImp.so If you'd run "file libOpenApiImp.so" I think it would tell you you've created a regular executable file, not a shared object. Note that -G is an option for Sun's own compiler, not g++. It doesn't do what you expect here.
To do this with gcc (or g++) you need to do something like this:
compile only: g++ -fpic -D_REENTRANT -I /usr/java/include -I /usr/java/include/solaris -I /home1/users/biyer/Bala/OAPI/include -c JavaC.C
link: g++ -shared JavaC.o -o libOpenApiImp.so
or compile and link in one step: g++ -fpic -shared -D_REENTRANT -I /usr/java/include -I /usr/java/include/solaris -I /home1/users/biyer/Bala/OAPI/include JavaC.C -o libOpenApiImp.so
/gordon
--
Lothar Kimmeringer - 06 Nov 2007 18:24 GMT > Can't load Sparc 32-bit .so on a Sparc 32-bit platform Google[0] points to http://forum.java.sun.com/thread.jspa?threadID=792436&messageID=9469362 Seems to be a cryptic message that has been introduced with a specific version of Java 1.5
You can go back to an older version to get meaningful messages or simply check the library for dependencies with other shared libraries that are not solved on that particular system.
Regards, Lothar
[0] http://www.google.de/search?hl=de&q=Can%27t+load+Sparc+32-bit+.so+on+a+Sparc+32- bit+platform&btnG=Google-Suche&meta=
 Signature Lothar Kimmeringer E-Mail: spamfang@kimmeringer.de PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)
Always remember: The answer is forty-two, there can only be wrong questions!
Bala - 06 Nov 2007 18:38 GMT On Nov 6, 1:24 pm, Lothar Kimmeringer <news200...@kimmeringer.de> wrote:
> > Can't load Sparc 32-bit .so on a Sparc 32-bit platform > [quoted text clipped - 16 lines] > Always remember: The answer is forty-two, there can only be wrong > questions! Hello,
I shifted to an older version and it says that there are symbols referred by my native function that are not found. My native method first initializes another dynamic library using the dlopen call and then calls a method of that dynamic library. This dynamic library in turn refers to a couple of static libraries as well.
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home1/ users/biyer/Bala/OAPI/src/libOpenApiImp.so: ld.so.1: java: fatal: relocation error: file /home1/users/biyer/Bala/OAPI/src/ libOpenApiImp.so: symbol _Z9OAPI_mainv: referenced symbol not found 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 OpenApi.<clinit>(OpenApi.java:7) at Main.main(Main.java:5)
Do i need to link the static libraries as well with my Java Application? If yes, how do i do it?
Thanx for the earlier help, it gave me an idea what was going wrong atleast
Lothar Kimmeringer - 06 Nov 2007 18:50 GMT > Do i need to link the static libraries as well with my Java > Application? If yes, how do i do it? From your other answer:
| I built the .so using the following command | g++ -Wno-deprecated -G -I/usr/java/include -I/usr/java/include/solaris | -I/home1/users/biyer/Bala/OAPI/include JavaC.C -o libOpenApiImp.so I don't know Solaris very much but when I compile under Linux it's necessary to compile it with -fPIC (and I always compile with -Wall, but that should be only a question of style here ;-)
Regards, Lothar
 Signature Lothar Kimmeringer E-Mail: spamfang@kimmeringer.de PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)
Always remember: The answer is forty-two, there can only be wrong questions!
Bala - 06 Nov 2007 18:54 GMT On Nov 6, 1:50 pm, Lothar Kimmeringer <news200...@kimmeringer.de> wrote:
> > Do i need to link the static libraries as well with my Java > > Application? If yes, how do i do it? [quoted text clipped - 16 lines] > Always remember: The answer is forty-two, there can only be wrong > questions! But my issue is that libOpenApiImp.so calls functions from 3 more static libraries, liba.a, libb.a and libc.a. Do these libraries need to be linked to Java application, because the only executing program here is the JAVA application. The error says that OAPI_Main refers to undefined symbols, which means its not able to find the methods that are in the static libraries..
Any comments on this?
Gordon Beaton - 06 Nov 2007 18:58 GMT > But my issue is that libOpenApiImp.so calls functions from 3 more > static libraries, liba.a, libb.a and libc.a. Do these libraries need > to be linked to Java application, because the only executing program > here is the JAVA application. When you link your shared object (see my other reply), you need to mention each of the dependent libraries with link options like this:
-L /path/to/your/libs -la -lb -lc
/gordon
--
Bala - 06 Nov 2007 20:28 GMT > > But my issue is that libOpenApiImp.so calls functions from 3 more > > static libraries, liba.a, libb.a and libc.a. Do these libraries need [quoted text clipped - 9 lines] > > -- Hi Gordon,
I used the command that you had pasted. The dynamic libraries got created but this time, even with an older version, i am getting just this message. Sorry to bother you much, but im just 2 months old in JAVA, so not sure which way to look at.. I have loads of other doubts and queries with respect to JNI. Once this issue gets solved, im gonna bang some more :)
Exception in thread "main" java.lang.UnsatisfiedLinkError: OAPIInit at OpenApi.OAPIInit(Native Method) at Main.main(Main.java:6)
java version "1.4.2_13" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_13-b06) Java HotSpot(TM) Client VM (build 1.4.2_13-b06, mixed mode)
Gordon Beaton - 06 Nov 2007 20:32 GMT > Exception in thread "main" java.lang.UnsatisfiedLinkError: OAPIInit > at OpenApi.OAPIInit(Native Method) > at Main.main(Main.java:6) You are making some progress; Unlike the previous errors, this one doesn't occur at System.loadLibrary(), it occurs when you try to invoke a native method.
This error says that the native method OAPIInit() doesn't exist in the library. You might disagree with that, but the JVM has a very specific idea of what the method needs to be called in order to find it.
javah should have produced a header file with the correct declaration. You should have included that header file in your source code, and used exactly those method declarations. Perhaps it's time for you to post your code.
/gordon
--
Bala - 06 Nov 2007 20:33 GMT > > > But my issue is that libOpenApiImp.so calls functions from 3 more > > > static libraries, liba.a, libb.a and libc.a. Do these libraries need [quoted text clipped - 27 lines] > Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_13-b06) > Java HotSpot(TM) Client VM (build 1.4.2_13-b06, mixed mode) Sorry, this problem seems to be solved. I had the wrong name mangling conversion in the JavaC.C file, which was causing the problem. Now my code executes, but dlopen failed due to some reason, will check that. The other dynamic library libSubscribe.so could not be loaded when i used dlopen to call it.
Gordon Beaton - 07 Nov 2007 10:14 GMT > Sorry, this problem seems to be solved. I had the wrong name > mangling conversion in the JavaC.C file, which was causing the > problem. This often indicates that you didn't exactly obey the method signatures generated by javah, since javah already declares the generated methods 'extern "C"' in the header file. For example if you changed any of the argument datatypes the declaration no longer has any effect.
> Now my code executes, but dlopen failed due to some reason, will > check that. The other dynamic library libSubscribe.so could not be > loaded when i used dlopen to call it. If libSubscribe.so has further dependencies (check with ldd) then the dynamic linker needs to be able to find them at runtime or libSubscribe.so itself will fail to load. Note that this depends on the flags you pass to dlopen(), in particular RTLD_LAZY or RTLD_NOW.
The dependent libraries, unlike libSubscribe.so, must either be in default locations (typically /lib and /usr/lib) or in one of the paths mentioned in LD_LIBRARY_PATH.
/gordon
--
Bala - 08 Nov 2007 22:31 GMT > > Sorry, this problem seems to be solved. I had the wrong name > > mangling conversion in the JavaC.C file, which was causing the [quoted text clipped - 22 lines] > > -- All the dependent libraries that libSubscribe.so is statically linked and are all static c libraries.
Loading of libSubscribe.so is successful now, but after that the Java's Main application tries to call the required native function, i am getting an error which i have pasted below the source code.
This is how my source code looks like Main.java - Executing Program ------------------------------ class Main { public static void main (String Args[]) { OpenApi openApi = new OpenApi(); openApi.OAPIInit (); } }
OpenApi.java - Used to generate OpenApi.h using javah ----------------------------------------------------- class OpenApi { public native void OAPIInit ();
static { System.loadLibrary ("OpenApiImp"); } }
JavaC.C - Used to create libOpenApiImp.so ------------------------------------------ #include "OpenApi.h" #include "jni.h" #include <Common.h> #include <dlfcn.h> #include <link.h>
JNIEXPORT void JNICALL Java_OpenApi_OAPIInit(JNIEnv *env, jobject obj) { if (!dlopen ("//home1//users//biyer//Bala//OAPI//src// libSubscribe.so", RTLD_GLOBAL)) { printf ("\n Library Loaded Successfully\n"); OAPI_main(); printf ("\n OAPI_Main Called\n"); } else printf ("\nError Loading the Dynamic Library\n"); }
Common.C - Used to generate libSubscribe.so ------------------------------------------- void OAPI_main() { printf ("\nIn OAPI Main\n"); OAPI_Init(); strcpy (FirmName, "BRAS"); OAPI_PASSPORT *Passport = GetAPassport (FirmName); OAPI_Logon (Passport); OAPI_start(); SpecialRequest(); My_mainloop(); }
All the functions called by OPAI_main are functions inside the static libraries which are linked to libSubscribe.so.
When i run Main.java, i get the error as i stated
java Main
Library Loaded Successfully ld.so.1: java: fatal: relocation error: file /home1/users/biyer/Bala/ OAPI/src/libOpenApiImp.so: symbol _Z9OAPI_mainv: referenced symbol not found Killed
Any thoughts why this could be happening? Does this mean that the static libraries havent got linked properly?
This is the command that i use to build both the shared libraries. libOpenApiImp.so ---------------- g++ -fpic -Wl,-G -Wl,-dy -Wno-deprecated -D_REENTRANT -DSOLARIS -DSUN4 -DSUN -DSVR4 -D_POSIX_PTHREAD_SEMANTICS -I/usr/java/include -I/usr/ java/include/solaris -I/home1/users/biyer/Bala/OAPI/include -I/home1/users/biyer/Bala/OAPI/ src JavaC.C /home1/users/biyer/Bala/OAPI/lib/libAdpt.a /home1/users/ biyer/Bala/OAPI/lib/libDef.a /home1/users/biyer/Bala/OAPI/lib/libxAdpt.a -o libOpenApiImp.so
libSubscribe.so --------------- g++ -fpic -Wl,-G -Wl,-dy -Wno-deprecated -D_REENTRANT -DSOLARIS -DSUN4 -DSUN -DSVR4 -D_POSIX_PTHREAD_SEMANTICS -I/usr/java/include -I/usr/java/include/ solaris -I/home1/users/biyer/Bala/OAPI/include -I/home1/users/biyer/Bala/OAPI/ src Common.C /home1/users/biyer/Bala/OAPI/lib/libAdpt.a /home1/users/ biyer/Bala/OAPI/lib/libDef.a /home1/users/biyer/Bala/OAPI/lib/libxAdpt.a -o libSubscribe.so
Joshua Cranmer - 09 Nov 2007 00:19 GMT > ld.so.1: java: fatal: relocation error: file /home1/users/biyer/Bala/ > OAPI/src/libOpenApiImp.so: symbol _Z9OAPI_mainv: referenced symbol not [quoted text clipped - 8 lines] > g++ -fpic -Wl,-G -Wl,-dy -Wno-deprecated -D_REENTRANT -DSOLARIS -DSUN4 > [snip] And there's your problem: you're using a C++ compiler to generate C code. Either use gcc or declare your methods to be C-based (extern "C").
The long of it: Inside the linked native libraries, there can only be one function by any given name. This is why C does not permit multiple functions of the same name. When C++ introduced this feature, the function names had to be modified by use of a specific mangling technique. So your "OAPI_main" become "_Z9OAPI_mainv" instead of "_OAPI_main"; the extra characters are a nice way of encoding its name to avoid conflicts.
By declaring functions to be C (or similar) via the `extern "C"' keywords, the compiler is instructed to not mangle these names as they produce the code.
P.S. Sorry to anybody if my oversimplified explanation of mangled names became too inaccurate.
 Signature Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth
Gordon Beaton - 09 Nov 2007 07:18 GMT > This is the command that i use to build both the shared libraries. > libOpenApiImp.so [quoted text clipped - 17 lines] > biyer/Bala/OAPI/lib/libDef.a > /home1/users/biyer/Bala/OAPI/lib/libxAdpt.a -o libSubscribe.so Joshua has already explained about the name mangling.
I just thought I'd mention that it's rather unconventional to specify static libraries as though they were unadorned object files, even though it might work for you. The "normal" way is to specify one or more library paths with -L, the each library with -l, like this:
-L /home1/users/biyer/Bala/OAPI/lib -lAdpt -lDef -lxAdpt
IMO this is both clearer and easier to maintain (lookup "DRY" on wikipedia). There may also be subtle differences in the way the linker treats the files as well, but that's just speculation.
/gordon
--
Bala - 12 Nov 2007 23:07 GMT > > This is the command that i use to build both the shared libraries. > > libOpenApiImp.so [quoted text clipped - 36 lines] > > - Show quoted text - Hello,
Thanx Joshua, I was able to run the application when i put OAPI_main in extern "C". Was a silly mistake. But the static libraries that i am using are compiled with CC 5.8. So g++ compiled code doesnt work for specific functions when it tries to call them. Hence i migrated my source compilation to CC, the same code just that i used CC instead of g++ to create the shared libraries. I am facing a different issue here.
Java program loads the first libOpenApiImp.so file properly, but this in turn fails to load libSubscribe.so. This works perfect with g++ compiled versions.
I created a shared library using CC with the following command
CC -G -D_REENTRANT -DSOLARIS -DSUN4 -DSUN -DSVR4 - D_POSIX_PTHREAD_SEMANTICS -I/usr/java/include -I/usr/java/include/ solaris -I/home1/users/biyer/Bala/OAPI/include -I/home1/users/biyer/ Bala/OAPI/src Common.cpp liba.a libb.b -o libSubscribe.so
Then i compiled my source as CC -DSOLARIS -DSUN4 -DSUN -DSVR4 -D_POSIX_PTHREAD_SEMANTICS -I/home1/ users/biyer/Bala/OAPI/include -I/home1/users/biyer/Bala/OAPI/src Main.cpp -o Main.o
Now when i run Main.o it says its not able to open the shared library. It prints an error message which is part of my code. "Error Loading the Dynamic Library"
I am also attaching the sample code in here.. The path of the library that i have mentioned is correct since the same code works fine with g+ + created shared library.
Please let me know if i need to do something differently if i am using CC.
Main.cpp -------- #include <iostream> #include <Common.h> #include <dlfcn.h> #include <link.h> #include <stdio.h>
using namespace std;
int main () { void *handle; void (*fptr)(); handle = dlopen ("./libSubscribe.so", RTLD_GLOBAL | RTLD_LAZY); if (handle == NULL) printf ("\nError Loading the Dynamic Library\n"); else { printf ("\n Library Loaded Successfully\n"); fptr = (void (*) ()) dlsym (handle, "OAPI_main"); if (fptr) { (*fptr)(); printf ("\n OAPI_Main Called\n"); } else { printf ("\nCould not find method\n"); } } return (0); }
Gordon Beaton - 13 Nov 2007 07:00 GMT > I was able to run the application when i put OAPI_main in extern > "C". Was a silly mistake. But the static libraries that i am using > are compiled with CC 5.8. So g++ compiled code doesnt work for > specific functions when it tries to call them. That seems to indicate that the static functions should have been declared extern "C".
Have you thought of using gcc (not g++), since your code really isn't c++ anyway... it could save you a lot of grief.
> Hence i migrated my source compilation to CC, the same code just > that i used CC instead of g++ to create the shared libraries. I am [quoted text clipped - 3 lines] > in turn fails to load libSubscribe.so. This works perfect with g++ > compiled versions. Are you saying that dlopen() fails, or dlsym()? Have you checked errno or called dlerror() so see why, instead of simply printing your own message indicating failure?
If dlopen() is failing, check (with "ldd") that libSubscribe.so has no further runtime dependencies, and (with "file") that it is a correctly built shared object. If there are additional runtime dependencies, they must be findable through LD_LIBRARY_PATH or in a standard place like /lib or /usr/lib.
If dlsym() is failing, make sure (with "nm" or "objdump") that the shared library contains the correct unmangled symbols you think it does.
You might consult the Solaris Linker and Libraries Guide, online at docs.sun.com.
BTW this is no longer a Java or JNI issue, consider taking it to a Solaris newsgroup.
/gordon
--
Bala - 13 Nov 2007 14:16 GMT > > I was able to run the application when i put OAPI_main in extern > > "C". Was a silly mistake. But the static libraries that i am using [quoted text clipped - 38 lines] > > -- Yeah sure. I will check it out on the solaris group, since it seems to be an issue with the way CC and g++ works. Thanx for all the help in this regard. Will get back once this issue is solved to discuss more about JNI stuff.
Thanks again for the timely help. Bala
Roedy Green - 06 Nov 2007 21:06 GMT >UnsatisfiedLinkError see http://mindprod.com/jgloss/runerrormessages.html#UNSATISFIEDLINKERROR
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|