dlopen() within a JNI-callable C++ function on Solaris?

S

Steve Gilbert

Hello,

I have a set of JNI-callable C++ routines in lib1.so,
From within one of these I would like to dlopen() a second
C++ library lib2.so.

dlopen() of this' second library always fails, with dlerror()
reporting
'ld.so.1: java: fatal: JNI_OnLoad: can't find symbol'

This second library is purely for local use within a single
JNI-callable routine. Example code below.

How can I make this work please?

Thanks
-- Steve

sun01% java -version
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

sun01% CC -V
CC: Forte Developer 7 C++ 5.4 2002/03/09


sun01% more Jmaster.java
import java.util.*;

public class Jmaster
{
static
{
System.loadLibrary("lib1");
};

private native void lib1doit();

public static void main(String[] dummy)
{
Jmaster me = new Jmaster();
me.lib1doit();
}
}

sun01% more liblib1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <link.h>
#include <errno.h>

#include "Jmaster.h"

JNIEXPORT void JNICALL Java_Jmaster_lib1doit(JNIEnv* env, jobject obj)
{
char* dlerr;

fprintf(stderr,"Loaded liblib1.so from Java, about to dlopen
liblib2.so\n");

// Open lib2

void* mydll = dlopen("liblib2.so",RTLD_NOW);
if ((dlerr=dlerror()) != NULL)
{
fprintf(stderr,"ERROR! dlopen of liblib2 failed: %s\n",dlerr);
exit(-1);
};

// Get call to 'lib2doit()'
void(*doit2)() = (void(*)()) dlsym(mydll,"lib2doit");
if ((dlerr=dlerror()) != NULL)
{
fprintf(stderr,"ERROR! dlsym of lib2doit failed: %s\n",dlerr);
exit(-1);
};

// Call 'doit2()'
doit2();

// Close lib2

dlclose(mydll);
if ((dlerr=dlerror()) != NULL)
{
fprintf(stderr,"ERROR! dlclose of liblib2 failed: %s\n",dlerr);
exit(-1);
};
};


sun01% more liblib2.cpp
#include <stdio.h>

extern "C" void lib2doit()
{
fprintf(stderr,"HELLO from lib2\n");
}

sun01% javac Jmaster.java
sun01% javah -jni Jmaster
sun01% CC -G liblib1.cpp -o liblib1.so -xildoff -library=Cstd
-features=no%strictdestrorder -ldl -I/usr/j2sdk1.4.2/include
-I/usr/j2sdk1.4.2/include/solaris
sun01% CC -G liblib2.cpp -o liblib2.so -xildoff -library=Cstd
-features=no%strictdestrorder
sun01%
sun01% java Jmaster
Loaded liblib1.so from Java, about to dlopen liblib2.so
ERROR! dlopen of liblib2 failed: ld.so.1: java: fatal: JNI_OnLoad:
can't find symbol
sun01%
 
G

Gordon Beaton

I have a set of JNI-callable C++ routines in lib1.so,
From within one of these I would like to dlopen() a second
C++ library lib2.so.

dlopen() of this' second library always fails, with dlerror()
reporting
'ld.so.1: java: fatal: JNI_OnLoad: can't find symbol'

I don't know why the second library fails, but I'll offer some random
thoughts and maybe something will help.

- I see that you test the results of dlopen() by calling dlerror(),
but I wonder you aren't seeing the most recent error, and *not* the
results of your (possibly successful) call to dlopen(). The JVM has
recently attempted to find (optional) JNI_OnLoad() in your first
library and doesn't care if it succeeded.

Check whether dlopen() returns NULL before you call dlerror(),
because maybe the library has actually loaded. (My manpage does say
that yours is the correct way to check whether dlsym() has failed
however).

- Does the second library have additional dependencies, or is it
really exactly the code you've posted? What does ldd say? Does nm
report any missing symbols?

- What happens if you use RTLD_LAZY instead? Does the error occur
later when you invoke the method?

- Perhaps you don't need to use dlopen() at all. You can invoke
functions directly in the second library, if when you build the
first library you tell the linker about its depedendencies on the
second one using linker options like "-f liblib2.so" to identify the
second library, and "-R /absolute/path" to add a runtime library
search path.

Hope this helps!

/gordon
 
S

Steve Gilbert

Gordon Beaton said:
I don't know why the second library fails, but I'll offer some random
thoughts and maybe something will help.

- I see that you test the results of dlopen() by calling dlerror(),
but I wonder you aren't seeing the most recent error, and *not* the
results of your (possibly successful) call to dlopen(). The JVM has
recently attempted to find (optional) JNI_OnLoad() in your first
library and doesn't care if it succeeded.

Check whether dlopen() returns NULL before you call dlerror(),
because maybe the library has actually loaded. (My manpage does say
that yours is the correct way to check whether dlsym() has failed
however).JNI_OnLoad()

Thank you, that was exactly it. The JVM had left an unread
message in dlerror() reporting that there was no JNI_OnLoad() in
the first library. I just needed to call dlerror() once at the
beginning of lib1 to clear that message and all was well.

-- Steve
 
G

Gordon Beaton

Thank you, that was exactly it. The JVM had left an unread message
in dlerror() reporting that there was no JNI_OnLoad() in the first
library. I just needed to call dlerror() once at the beginning of
lib1 to clear that message and all was well.

Or, you could define JNI_OnLoad() in lib1. That way, you can load lib2
as part of its initialization, and if that fails, let the error
propagate so the JVM "fails" to load lib1.

/gordon
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top