Weiqi,

You are right.  That's the problem.  Sorry for the careless mistake.

To make the code more interesting, I add two threads, t1 and t2, in the code
this time and found some problems, maybe they are my problems again :( 

Q1:  Based on JNI spec, different native functions in the same thread should
get the same JNIEnv pointer, and native functions in different threads
should receive different JNIEnv pointers.  In other words, JNIEnv pointer
should be thread unique.  But I couldn't see this (see attached running
result and code).  Also, I found jobjects passed to native function from
different calling objects are the same (again, see attached result and code)
when using BlackDown 1.1.8 v1.  I run the same java app and dlls (same
contents as so1 and so2) on NT by using jdk 1.2 coming with VisualCafe4.0,
it seems jobjects passed to native function from different calling objects
are different (as expected, because native function is called from different
thread objects, t1 and t2.  see attached code please).  I don't know why the
behavior is different on Linux and NT (or between BlackDown 1.1.8 v1 and
jdk1.2)

Q2:
Based on the running result, it seems every time when call back from so1 to
so2 in either t1 or t2 thread context, so2 always uses the second thread
t2's *JNIEnv to call back to java.  But we need so2 call back to so1 then
java in its own thread context.

Note: attached codes are real and can be compiled to .class, .h, .o and .so

Could someone take a look and see what I did wrong?  I learned a lot
recently from this group.

Thank you and have a nice Lunar New Year!



Lee

===========================================

///////////////////////////////////////////
//running result
///////////////////////////////////////////
/mnt/e/Linux/java/jni/java_so_so_4>java -native app
*** in main() ***
*** in t1's loadSo2, jEnv = -1086325736
*** in t1's loadSo2, *jEnv = 1074234656
*** in t1's loadSo2, _this = 1
*** hello from so2 ***

*** in t2's loadSo2, jEnv = -1088422888
*** in t2's loadSo2, *jEnv = 1074234656
*** in t2's loadSo2, _this = 1
*** hello from so2 ***

*** in t2's backToJava, gEnv = -1088422888
*** in t2's backToJava, *gEnv = 1074234656
*** in t2's backTojava, gObj = 1
***** In Java, called back from so1

*** in t2's backToJava, gEnv = -1088422888
*** in t2's backToJava, *gEnv = 1074234656
*** in t2's backTojava, gObj = 1
***** In Java, called back from so1

*** in t2's backToJava, gEnv = -1088422888
*** in t2's backToJava, *gEnv = 1074234656
*** in t2's backTojava, gObj = 1
***** In Java, called back from so1

*** in t2's backToJava, gEnv = -1088422888
*** in t2's backToJava, *gEnv = 1074234656
*** in t2's backTojava, gObj = 1
***** In Java, called back from so1

/mnt/e/Linux/java/jni/java_so_so_4>

===========================================

///////////////////////////////////////////
//app.java
///////////////////////////////////////////
public class app 
{
    static public void main(String args[]) 
    {
      System.out.println("*** in main() ***");

        myThread t1 = new myThread("t1");
        myThread t2 = new myThread("t2");

        t1.start();
        t2.start();
    } 

    static
    {
        System.loadLibrary("so1_beep");
    }
}


class myThread extends Thread
{
        myThread(String tID)
        {
                super(tID);
        }

        native void loadSo2(String msg);

        public void run()
        {
                loadSo2(this.getName());
        }

        void callBack()
        {
                System.out.println("***** In Java, called back from so1\n");
        }
}

===========================================

///////////////////////////////////////////
//so1_beep.c
///////////////////////////////////////////
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include "myThread.h"


JNIEnv *gEnv;
jobject gObj;
char szTmp[20];

void Java_myThread_loadSo2(JNIEnv * jEnv, jobject _this, jstring jMsg)
{
        void *library;
        void (*soHello)(void);
        const char *error;

        const char * msg;

        msg = (*jEnv)->GetStringUTFChars(jEnv, jMsg, 0);
        printf("*** in %s's loadSo2, jEnv = %d\n", msg, jEnv);
        printf("*** in %s's loadSo2, *jEnv = %d\n", msg, *jEnv);
        printf("*** in %s's loadSo2, _this = %d\n", msg, _this);
        strcpy(szTmp, msg);
        (*jEnv)->ReleaseStringUTFChars(jEnv, jMsg, msg);

        gEnv = jEnv;
        gObj = _this;

        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");

        printf("*** in %s's backToJava, gEnv = %d\n", szTmp, gEnv);
        printf("*** in %s's backToJava, *gEnv = %d\n", szTmp, *gEnv);
        printf("*** in %s's backTojava, gObj = %d\n", szTmp, gObj);

        if(mid == 0)
        {
                printf("*** in so1, mid = 0 ***\n");
                exit(1);
        }

        (*gEnv)->CallVoidMethod(gEnv, gObj, mid);
}

===========================================

///////////////////////////////////////////
//so2_hello.c
///////////////////////////////////////////
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>


print_hello()
{
        int i;

        void (*backToSo1)(void);
        void *library;
        const char *error;

        printf("*** hello from so2 ***\n\n");

        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);
        }
        
        for(i=0; i<2; i++)
        {
                sleep(1);
                
                (*backToSo1)();
        }
}




-----Original Message-----
From: Weiqi Gao [mailto:[EMAIL PROTECTED]]
Sent: Thursday, February 03, 2000 7:23 PM
To: Xing, Lee
Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED];
[EMAIL PROTECTED]
Subject: Re: JNI & .so Files


[EMAIL PROTECTED] wrote:
> 
>         jmethodID mid = (*gEnv)->GetMethodID(gEnv, cls, "callBack",
"(V)V");

It's "()V" not "(V)V".  It worked on my machine after the change.

--
Weiqi Gao
[EMAIL PROTECTED]


----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]


----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to