不好意思請教如何由C code"自動"callback回java method

2009.07.21 06:55PM
不好意思請教如何由C code"自動"callback回java method

 

各位好:
    小弟目前必須使用JNI的invocation API去cearteVM再找到特定的object並呼叫其方法,
, 呼叫物件方法如果由java call C的時候是很容易實作的因為與JVM的通道是由java打開 , 但是如果今天倒過來要由C呼叫java中的物件(與JVM的通道是由C打開)這樣的話就不是很清楚該怎麼做 , 因為C的部分是在linux下執行所以有想過應該是要create一個thread讓他可以使用invocation API指回JVM 再去找java物件 , 因為小弟我不熟linux的東西 , 不曉得各位是否可以推薦相關的網站或是資料可以給小弟參考 , 或是知道這種issue應該要由怎樣的方向下手會比較好 , 請給小弟一些建議

thanks a lot

 

4 則回應

  • 果然站上隱藏著強者啊!!!!!!

    2009-08-12
  • #include <stdio.h>
    #include <jni.h>
    #include <string.h>

    JNIEnv* create_vm(JavaVM ** jvm)

    {

        JNIEnv *env;
        JavaVMInitArgs vm_args;
        JavaVMOption options[2];

        options[0].optionString = "-Djava.compiler=NONE"; 
        options[1].optionString = "-Djava.class.path=."; /* user classes */

        vm_args.version = JNI_VERSION_1_4; //JDK version.
        vm_args.options = options;
        vm_args.nOptions = 2;
        vm_args.ignoreUnrecognized = 0;

        int ret = JNI_CreateJavaVM(jvm, &env, &vm_args);
        if(ret < 0)
            printf("\nUnable to Launch JVM %d\n",ret);
        return env;
    }

    int main(int argc, char* argv[])
    {
        JNIEnv *env;
        JavaVM * jvm;
        env = create_vm(&jvm);

        if (env == NULL)
            return 1;

        jclass clsH =NULL;

        jmethodID midMain = NULL;
        jmethodID midCalling = NULL;

       clsH = env->FindClass("Hello");

      if (clsH != NULL)
        {
            midMain       = env->GetStaticMethodID(clsH, "main", "([Ljava/lang/String;)V");
            midCalling    = env->GetStaticMethodID(clsH,"TestCallMethod","(Ljava/lang/String;)V");
        }
        else
        {
            printf("\nUnable to find the requested class\n");
        }

        /************************************************************************/
        /* Now we will call the functions using the their method IDs            */
        /************************************************************************/
        if(midMain != NULL)
            env->CallStaticVoidMethod(clsH, midMain, NULL); //Calling the main method.

        if (midCalling!=NULL)
        {
            jstring StringArg = env->NewStringUTF("\nTestCall:Called from the C Program\n");
            //Calling another static method and passing string type parameter
            env->CallStaticVoidMethod(clsH,midCalling,StringArg);
        }

        //Release resources.
        int n = jvm->DestroyJavaVM();
        return 0;
    }
     

     

    2009-08-11
    • 非常感謝這位好心的同好的回應:

      你所提出的解答是屬於C要呼叫一般的java的做法 , 在android平台上不太一樣 , 在android上可以直接經由JNI_OnLoad(JavaVM *vm,void *reserved)直接取得指向android dalvik vm的ponter , 但現在我的問題是卡在 , 我將該pointer存在一個static global JavaVM* , 讓其他的thread可以使用 , 在一般的C呼叫java可行但是在android卻不行 , 找過很多相關的資料也都是相同的做法當然都不是android平台就是 , 換句話說android平台在invocation API這部分似乎和一般的JNI寫法應該有不同的地方 , 畢竟android的VM是自家做的跟一般的java VM有不同 , 不曉得有沒有人知道這個問題怎解 , 或是大家有不同的想法可以提出來討論一下

      感謝

      michtw wrote:

      #include <stdio.h>
      #include <jni.h>
      #include <string.h>

      JNIEnv* create_vm(JavaVM ** jvm)

      {

          JNIEnv *env;
          JavaVMInitArgs vm_args;
          JavaVMOption options[2];

          options[0].optionString = "-Djava.compiler=NONE"; 
          options[1].optionString = "-Djava.class.path=."; /* user classes */

          vm_args.version = JNI_VERSION_1_4; //JDK version.
          vm_args.options = options;
          vm_args.nOptions = 2;
          vm_args.ignoreUnrecognized = 0;

          int ret = JNI_CreateJavaVM(jvm, &env, &vm_args);
          if(ret < 0)
              printf("\nUnable to Launch JVM %d\n",ret);
          return env;
      }

      int main(int argc, char* argv[])
      {
          JNIEnv *env;
          JavaVM * jvm;
          env = create_vm(&jvm);

          if (env == NULL)
              return 1;

          jclass clsH =NULL;

          jmethodID midMain = NULL;
          jmethodID midCalling = NULL;

         clsH = env->FindClass("Hello");

        if (clsH != NULL)
          {
              midMain       = env->GetStaticMethodID(clsH, "main", "([Ljava/lang/String;)V");
              midCalling    = env->GetStaticMethodID(clsH,"TestCallMethod","(Ljava/lang/String;)V");
          }
          else
          {
              printf("\nUnable to find the requested class\n");
          }

          /************************************************************************/
          /* Now we will call the functions using the their method IDs            */
          /************************************************************************/
          if(midMain != NULL)
              env->CallStaticVoidMethod(clsH, midMain, NULL); //Calling the main method.

          if (midCalling!=NULL)
          {
              jstring StringArg = env->NewStringUTF("\nTestCall:Called from the C Program\n");
              //Calling another static method and passing string type parameter
              env->CallStaticVoidMethod(clsH,midCalling,StringArg);
          }

          //Release resources.
          int n = jvm->DestroyJavaVM();
          return 0;
      }
       

       

       

      2009-08-12