Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JNI calls to multiple libraries

766 views
Skip to first unread message

Jonathan Doughty

unread,
Sep 25, 1997, 3:00:00 AM9/25/97
to

>>>>> David S Goldberg <d...@linus.mitre.org> writes:

> I'm using JNI to write a Java class that will be used for network
> monitoring. I'm using the pcap library from ftp.ee.lbl.gov for the
> network monitoring part. I've defined some native methods that make
> calls into the pcap library. The problem is that when my native
> method gets called, the pcap library isn't available to it. I've
> tried loading the pcap library (I've made a shared lib out of it with
> the appropriate CFLAGS and ld -G in the pcap build directory) with
> System.loadLibrary, which works fine as far as the jvm is concerned
> (no errors when java is run), but when my native method gets called, I
> get undefined reference errors to the pcap library functions. The
> workaround for now has been to build a single library that includes
> both my native method implementation and the pcap library, but there's
> got to be a cleaner way. How else to use other system librarys like
> libm or libsocket etc?

And Steven Brodhead <stb...@concentric.net> replied:

> Beg Sun to fix the native method dynamic linking problem in the JVM
> ASAP. It has been reported to them and is trivial to fix. The Solaris
> JVM can't find native methods in the "last loaded" native library. One
> workaround is to forcibly load a dummy library last so that your
> library is NOT the last one. (I am assuming you have a correct
> LD_LIBRARY_PATH. If your library is not in the LD...path, you will get
> a different exception.)

I had a problem similar to David's and Steven's fix didn't work for me
(if I understood him to mean, use System.loadLibrary() to load a dummy
last library). In fact, I had the same problem using multiple shared
libraries on Linux too, so, while it may be JDK JVM related it's not
just the Solaris JVM. I've solved my problem, at least in a test
environment, using a Java application calling a JNI shared library in
C, which in turn makes calls to another non-system shared library also
in C.

My solution turns out not to need a dummy library. I thought about
the problem and reasoned, since I was having difficulty dynamically
linking to another C library from the C-based JNI library, maybe the
linker was getting confused by trying to do the System.loadLibrary()
of an application specific, non-JNI, library from the Java
application. So I looked at dlopen(), the C interface to the dynamic
libraries. What I ended up doing was, in my JNI C library I do:

#include <dlfcn.h>
...
void *handle;

handle = dlopen("libother.so", RTLD_LAZY | RTLD_GLOBAL);
if (handle == NULL) {
fputs (dlerror(), stderr);
return;
}
...
fn_in_other_lib(); /* call function in libother.so */

That works! The RTLD_LAZY | RTLD_GLOBAL seems to be one required
element, just RTLD_LAZY alone wouldn't do the job. And, it turns out
that, on Linux it didn't matter if I left the System.loadLibrary("other")
call in, but on Solaris, that seemed to the run time loader. I removed
System.loadLibrary("other") from the Java app and instead do the
dlopen("other") on the C side of things.

The dlopen man page on Linux says (if I recall correctly) that if
there is an entry point in the library named _init then it'll get
executed when the library is loaded. I think I saw something similar
in Solaris's ld page or somewhere. So, I might try making one of
those in my JNI library to do dlopen()s of all the other libraries I
need. Alternatively maybe I can make a private native JNI method that
gets called by my JNI class's static initializer after the C JNI
implementation library is loaded. Thinking about it, I sort of like
using dlopen in place of loadLibrary since it gets the dependencies
closer to their source: why should Java care what libraries it needs
to load other than the JNI one. It would be nice if the JNI tutorials
went that extra step to demonstrate how to load other legacy support
libraries but maybe that's not a general problem on non-Unix
platforms.

I couldn't find anything about this problem or it's solution at Sun's
Java Developer Connection site either, which has a pretty reasonable
knowledge base of questions and answers. I'm surprised since surely
other people have legacy applications they're trying to retro-fit with
Java front ends.

--
Jonathan Doughty The MITRE Corporation j...@mitre.org


Sheng Liang

unread,
Sep 27, 1997, 3:00:00 AM9/27/97
to Jonathan Doughty

This is a rather common problem in building native libraries,
not just JNI. If you want to ship a library A that depends on
library B, you must specify an *explicit* dependency on B when
you build A. On Solaris, this can be accomplished by passing
the -l option to the ld command.

Another alternative, as j...@mitre.org has already pointed out,
is to explicitly load B into the global name space. This approach
works, but is not the preferred one, because only A needs to see
the functions exported from B, not other libraries.

Sheng Liang
JavaSoft

James P. Yu

unread,
Sep 30, 1997, 3:00:00 AM9/30/97
to

Jonathan Doughty wrote:

> >>>>> David S Goldberg <d...@linus.mitre.org> writes:
>
> > I'm using JNI to write a Java class that will be used for network
> > monitoring. I'm using the pcap library from ftp.ee.lbl.gov for the
> > network monitoring part. I've defined some native methods that make
> > calls into the pcap library. The problem is that when my native
> > method gets called, the pcap library isn't available to it. I've
> > tried loading the pcap library (I've made a shared lib out of it with
> > the appropriate CFLAGS and ld -G in the pcap build directory) with
> > System.loadLibrary, which works fine as far as the jvm is concerned
> > (no errors when java is run), but when my native method gets called, I
> > get undefined reference errors to the pcap library functions. The
> > workaround for now has been to build a single library that includes
> > both my native method implementation and the pcap library, but there's
> > got to be a cleaner way. How else to use other system librarys like
> > libm or libsocket etc?
>
>

We have the similiar situation like yours too. We remedied it by linking
the other shared library through the linker - the last step of building your
JNI shared library. The linker command line looks like:

g++ -G -Wl,-R/....../lib -o mysharedlib.so libother_1.so libother_2.so
libother_3.so <RETURN>

Of course, the "otherlib*.so" has to be build as shared lib too with -G
argument.

I am not sure if you can replace the above command line with:

g++ -G -Wl,-R/....../lib -o mysharedlib.so -lother_1 -lother_2 -lother_3
<RETURN>

Maybe that would work too. But the key issue here, is to resolve all the
symbols inside mysharedlib.so at link time.

-James


Sven Goethel

unread,
Oct 1, 1997, 3:00:00 AM10/1/97
to j...@cs.umbc.edu

James P. Yu wrote:
>
> Jonathan Doughty wrote:
>
> > >>>>> David S Goldberg <d...@linus.mitre.org> writes:
> >

(SNIPPED)


> We have the similiar situation like yours too. We remedied it by linking
> the other shared library through the linker - the last step of building your
> JNI shared library. The linker command line looks like:
>
> g++ -G -Wl,-R/....../lib -o mysharedlib.so libother_1.so libother_2.so
> libother_3.so <RETURN>
>
> Of course, the "otherlib*.so" has to be build as shared lib too with -G
> argument.
>
> I am not sure if you can replace the above command line with:
>
> g++ -G -Wl,-R/....../lib -o mysharedlib.so -lother_1 -lother_2 -lother_3
> <RETURN>
>

YES - we used '-l<LibBaseName>' for shared libs and it worked !
The final target shared lib is independent where <LibBaseName>
resides! ld just looks in all LD_LIBRARY_PATH path's ;-))


We used that for our GL4Java !
o linux OK
o solaris OK
o aix NOT (because we were the only shared lib :-()


> Maybe that would work too. But the key issue here, is to resolve all the
> symbols inside mysharedlib.so at link time.
>
> -James

sven - peace
--
mailto:s_go...@bielefeld.netsurf.de
www : http://www.bielefeld.netsurf.de:8080/~s_goethel
www : http://www.t-online.de/sgoethel
voice : 0521-2399440, 089-78581663 089-72223439 (work)

0 new messages