Hi Nathan,
Thank you very much for your information. I created three small real files
(app.java, so1_beep.c and so2_hello.c) and attach them below. They can be
compiled into .class, .h, .o and .so files. I'm using BlackDown 1.1.8 v1 on
RH6.1
It seems so2 can call back to so1, but when so1 calls back to java app, a
segment error happens. I checked the code many times but still couldn't
figure out why. I have a feeling that saving JNIEnv and jobject in so1 to
global vars may have problem but not sure. Thank you and forgive me for
this long e-mail.
The error msg is long. It looks like:
============================================
SIGSEGV 11* segmentation violation
stackbase=BFFFF8C8, stackpointer=BFFFF248
Full thread dump:
...
...
app.main(app.java:8)
Monitor Cache Dump:
Registered Monitor Dump:
Thread queue lock: <unowned>
Name and type hash table lock: <unowned>
String intern lock: <unowned>
JNI pinning lock: <unowned>
JNI global reference lock: <unowned>
BinClass lock: <unowned>
Class loading lock: <unowned>
Java stack lock: <unowned>
Code rewrite lock: <unowned>
Heap lock: <unowned>
Has finalization queue lock: <unowned>
Finalize me queue lock: <unowned>
Waiting to be notified:
"Finalizer thread" (0x80af440)
Monitor registry: owner "main" (0x80a3b78, 1 entry)
Aborted
============================================
//app.java
public class app
{
static public void main(String args[])
{
System.out.println("*** in main() ***");
toNative app = new toNative();
app.loadSo2("*** call load_so2() from java ***");
}
}
class toNative
{
toNative()
{
System.loadLibrary("so1_beep");
}
native void loadSo2(String msg);
void callBack()
{
System.out.println("In Java, called back from so1");
}
}
============================================
//so1_beep.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "toNative.h"
JNIEnv *gEnv;
jobject gObj;
void Java_toNative_loadSo2(JNIEnv * jEnv, jobject _this, jstring jMsg)
{
void *library;
void (*soHello)(void);
const char *error;
gEnv = jEnv; //save them in global vars to let local function
gObj = _this; //backToJava() use them to call back to java app.
printf("*** so1: in loadSo2() before dlopen() ***\n");
library = dlopen("./libso2_hello.so", RTLD_LAZY);
if(library==NULL)
{
fprintf(stderr, "Could not open libso2_hello.so: %s\n",
dlerror());
exit(1);
}
dlerror();
soHello = (void *) dlsym(library, "print_hello");
error = dlerror();
if(error)
{
fprintf(stderr, "Could not find print_hello(): %s\n",
error);
exit(1);
}
(*soHello)();
}
void backToJava()
{
jclass cls = (*gEnv)->GetObjectClass(gEnv, gObj);
jmethodID mid = (*gEnv)->GetMethodID(gEnv, cls, "callBack", "(V)V");
printf("*** in backToJava() ***\n"); //**** I can see this msg after
run it
//and before the
segmentation error.
(*gEnv)->CallVoidMethod(gEnv, gObj, mid);
}
============================================
//so2_hello.c
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
print_hello()
{
void (*backToSo1)(void);
void *library;
const char *error;
library = dlopen("./libso1_beep.so", RTLD_LAZY);
if(library==NULL)
{
fprintf(stderr, "Could not open libso1_beep.so in
libso2_hello.so:%s\n", dlerror());
exit(1);
}
dlerror();
backToSo1 = (void *) dlsym(library, "backToJava");
error = dlerror();
if(error)
{
fprintf(stderr, "Could not find backToJava(): %s\n", error);
exit(1);
}
while(1)
{
sleep(1);
(*backToSo1)();
}
}
============================================
-----Original Message-----
From: Nathan Meyers [mailto:[EMAIL PROTECTED]]
Sent: Thursday, February 03, 2000 1:27 PM
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]
Subject: Re: JNI & .so Files
On Thu, Feb 03, 2000 at 12:28:25PM -0600, [EMAIL PROTECTED] wrote:
> Hi Nathan,
>
> Thank you for your response. Please let me re-address my question by
using
> the following pseudo code. I embedded my question in so2.c pseudo code.
Thanks, that helps. You're simply trying to get a symbol address so you
can call it. You could use the same technique in so2 that you used in
so1: dlopen() to load the library and dlsym() to look up a symbol.
Yes, it appears that dlopen() is redundant, since the so1 library is
already loaded... but that's not a problem. Calling dlopen() on that
library will not load another copy, it will just increase a refcount
maintained by the system. More importantly, it'll return a handle you
can use in a dlsym() call.
Nathan
>
> The following lines are app.java, so1.c and so2.c. They are only pseudo
> code.
>
> ======================================
> //app.java
> public class app
> {
> static
> {
> System.loadLibrary("so1");
> }
> native void so1Func();
>
> public static void main(String args[])
> {
> app myApp = new app();
> myApp.so1Func();
> }
>
> javaFunc()
> {
> System.out.printfln("In Java, called back from so1.so");
> }
>
> }
> ======================================
> //so1.c for libso1.so
> JNIEnv gEnv;
> jobject gObj;
>
> void Java_app_so1Func(JNIEnv * jEnv, jobject _this)
> {
> gEnv = jEnv;
> gObj = _this;
> ...
> library = dlopen("./libso2.so", RTLD_LAZY);
> funcRef = dlsym(library, "so2Func");
> (*funcRef)(); //call function so2Func() in libso2.so
> ...
> }
>
> void callBack()
> {
> jclass cls = (*gEnv)->GetObjectClass(gEnv, gObj);
> jmethodID mid = (*gEnv)->GetMethodID(gEnv, cls, "javaFunc", "(V)V");
> (*gEnv)->CallVoidMethod(gEnv, gObj, mid); //call back to java app.
> }
> ======================================
> //so2.c for libso2.so
> so2Func()
> {
> while(1)
> {
> ...
> //********************************
> //how to call back to the function
> //callBack() in libso1.so from here?
> //********************************
> ...
> }
> }
>
> app.java loads libso1.so into its address space, and libso1.so loads
> libso2.so into the same address space. So, libso2.so should be able to
call
> a function in libso1.so (in the same address space) if libso2.so can
resolve
> that function's symbol, but how?
>
> Thanks.
>
>
> Lee
>
>
> -----Original Message-----
> From: Nathan Meyers [mailto:[EMAIL PROTECTED]]
> Sent: Wednesday, February 02, 2000 10:44 PM
> To: [EMAIL PROTECTED]
> Cc: [EMAIL PROTECTED]
> Subject: Re: JNI & .so Files
>
>
> [EMAIL PROTECTED] wrote:
> >
> > Hi,
> >
> > I got a question on JNI. It would be appreciated if someone could help.
>
> Lee,
>
> I'm having trouble understanding the problem you're posing. What is the
> difficulty you're trying to solve... how to call functions in one .so
> from another .so? You're already doing that.
>
> Is it the problem of figuring out how to call a function whose name you
> do not know until runtime? If so, I think you'll find the
> dlopen()/dlsym()/dlclose() functions useful. Other than that
> possibility, I'm not quite sure what problem you're trying to solve.
>
> Nathan
>
>
> >
> > Q:
> > In order to hide java and jni related issues (e.g. jni function name
> > convention, etc.) from .so programmers, a wrapper .so file so1.so is
used
> in
> > between java app and another .so file so2.so (the one with native
> functions
> > we need). This way, the java app interacts with the wrapper so1.so
> > directly. Every time when java app needs a native function service in
> > so2.so, it first calls a native function in so1.so through jni. so1.so,
> in
> > turn, calls the required function in so2.so. Everything works fine in
> this
> > direction (i.e. java app->so1.so->so2.so. java app loads so1.so, and
> so1.so
> > loads so2.so, then java app invokes a function in so2.so through a
> function
> > in so1.so). The question is how a function in so2.so calls back to java
> app
> > through a function in so1.so? In fact, we only need to know how
functions
> > in so2.so can call functions in so1.so because jni will let us call back
> to
> > java app from so1.so.
> >
> > More information:
> > - the java app is multithreaded application using Thread.start().
> > - each java thread may call the same function in so1.so, then
> > this function, in turn, calls a function in so2.so
> > - native code doesn't create any thread.
> >
> > Use IPC? which one is easier on Linux? Is there any other mechanism
> > for this on Linux?
> >
> > A simple sample code will help a lot.
> >
> > Thank you.
> >
> > Lee
> >
> > ----------------------------------------------------------------------
> > To UNSUBSCRIBE, email to [EMAIL PROTECTED]
> > with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
--
[EMAIL PROTECTED] Public Access User -- Not affiliated with Teleport
Public Access UNIX and Internet at (503) 220-1016 (2400-28800, N81)
----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]