I have two shared objects from C++ modules. One calls functions inside the
other. I want to use both of them through JNI.
If I load them using separate "System.loadLibrary" calls in my java app,
will one shared object be able to resolve its called to functions within the
other shared object?
Also, I'm getting an error from loading the shared object, that may or may
not be related to the same problem. Any idea what it means? I'm not sure
how to tell what that symbol is referring to that its not finding in the
shared object itself.
$> java DBTest
Exception in thread "main" java.lang.UnsatisfiedLinkError:
/vob/itex_tools/MAP/common/lib/libMAP_Util.so: ld.so.1:
/vob/external_sw/java/jdk/bin/../bin/sparc/native_threads/java: fatal:
relocation error: file /vob/itex_tools/MAP/common/lib/libMAP_Util.so: symbol
__1cDstdMout_of_rangeG__vtbl_: referenced symbol not found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1382)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1306)
at java.lang.Runtime.loadLibrary0(Runtime.java:749)
at java.lang.System.loadLibrary(System.java:820)
at DBTest.<clinit>(DBTest.java:51)
>I have two shared objects from C++ modules. One calls functions inside the
>other. I want to use both of them through JNI.
>
>If I load them using separate "System.loadLibrary" calls in my java app,
>will one shared object be able to resolve its called to functions within the
>other shared object?
You might get lucky, but it would be better if the first one expressed an
explicit dependency on the second one.
>Also, I'm getting an error from loading the shared object, that may or may
>not be related to the same problem. Any idea what it means? I'm not sure
[quoted text clipped - 7 lines]
>relocation error: file /vob/itex_tools/MAP/common/lib/libMAP_Util.so: symbol
>__1cDstdMout_of_rangeG__vtbl_: referenced symbol not found
That's a C++ mangled symbol name.
You didn't say what operating system you're on, but from the message above
I gather it's Solaris, so:
- You should construct your shared objects with explicit references
to their dependencies, so that e.g. "ldd -r libMAP_Util.so"
succeeds (i.e. doesn't complain about any unresolved references)
without resorting to nonsense like LD_LIBRARY_PATH or ld.config.
This will probably involve using -l, -L and -R when you build the
shared objects.
If you are using sufficiently recent versions of Solaris (Solaris
8 and above, I think, but you would need to check), then $ORIGIN
with -R should be very helpful.
One way to keep yourself honest is to add "-z defs" to the linker
flags in your Makefile for the shared objects.
- Incidentally, do NOT call 'ld' directly to build the shared objects;
always use your compiler frontend ('cc', 'CC', 'gcc', whatever) to
invoke the linker for you.
This may mean that you have to use funny syntax (such as "-Wl,") to
tell the compiler frontend to pass a linker option (e.g. "-z defs")
through to the linker for you.
- C++ makes all this a bit more complicated. If it were me I would
try to avoid C++ and just use C for everything in the shared objects,
but...
- If you do have to use C++, be aware that (unless things have changed
while I wasn't paying attention) gcc's C++ uses different calling
conventions, libraries etc than Sun's C++ compiler. Personally I
wouldn't want to try mixing the two of them in one address space,
and I believe that parts of the JVM already use Sun's C++ compiler,
so that means if I had to use C++ for a shared object that's loaded
into the JVM I would want to use Sun's C++ compiler (preferably the
same version that was used to build the JVM), not gcc, in the
interests of a quiet life. But that's just me.
- Also, regardless of whether your code is C or C++, make sure that
all your code is MT-safe, because (unless you carefully skirt this
in your Java code) your JNI code may be invoked concurrently from
multiple threads. (Of course this isn't peculiar to Solaris, it's
true for JNI code on any platform. It used to be worse on Solaris
because of ye olde Green Threads in the JVM, but thankfully these
days the JVM on Solaris uses native threads).
Thomas Maslen
maslen@wedgetail.com
greenpm - 24 Sep 2004 18:57 GMT
Thomas,
I don't understand your answer.
I receive the following error message:
Exception in thread "main" java.lang.UnsatisfiedLinkError:
/vobs/eis/src/cpp/lib/libjni_flnt.so: ld.so.1: java: fatal: relocation
error: file /vobs/eis/src/cpp/lib/libjni_flnt.so: symbol
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc: referenced symbol
not found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1473)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1397)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:832)
at com.fmr.eis.flnt.Session.<clinit>(Session.java:18)
I'm building the library with the following command:
gcc -G -o /vobs/eis/src/cpp/lib/libjni_flnt.so
com_fmr_eis_flnt_Session.o
From your response it sounds like I need to add some option when building
the shared library but I couldn't gleen from your message what that option
might be.
Can you help me?
Thanks,
Paul
p.s. I'm running Solaris 8.