关于JNI的一些琐碎

首先在Java中调用C++实现的native方法,在该方法中,我又创建了一个线程,代码请见最下面。

1. 如何在这个新建的线程中调用Java代码?

JavaVM *g_jvm;

DWORD __stdcall ThreadProc(void*) {
  MessageBoxA(NULL, "os thread", "demo", 0);

  JNIEnv *env = NULL;
  g_jvm->AttachCurrentThread((void**)&env, 0);
  jclass cls = env->FindClass("com/company/JNIDemo");

  jmethodID mid = env->GetStaticMethodID(cls, "sayHello", "(Ljava/lang/String;)Ljava/lang/String;");
  const char* name = "World";
  jstring arg = env->NewStringUTF(name);
  jstring result = (jstring)env->CallStaticObjectMethod(cls, mid, arg);
  const char* str = env->GetStringUTFChars(result, 0);
  MessageBoxA(NULL, str, str, 0);
  env->ReleaseStringUTFChars(result, 0);
  return 0;
}

g_jvm这个变量我会在Java调用的那个由C实现的native方法中初始化。在Java代码中我分别在main()和sayHello()两个函数中输出currentThread().getId(),它们的值是不同的。

值得注意的是,如果直接在C native中保存JNIEnv,在新建的线程中是无法使用它的。这里我仅实验了调用静态方法。

 

2. 如何在新建的操作系统线程中调用一个已有的Java对象非静态成员方法? 

JavaVM *g_jvm;
jobject g_obj;

DWORD __stdcall ThreadProc(void*) {
  MessageBoxA(NULL, "os thread", "demo", 0);

  JNIEnv *env = NULL;
  g_jvm->AttachCurrentThread((void**)&env, 0);
  jclass cls = env->FindClass("com/company/JNIDemo");

  jmethodID mid = env->GetMethodID(cls, "sayHello", "()Ljava/lang/String;");
  jstring result = (jstring)env->CallObjectMethod(g_obj, mid);
  const char* str = env->GetStringUTFChars(result, 0);
  MessageBoxA(NULL, str, str, 0);
  env->ReleaseStringUTFChars(result, 0);

  env->DeleteLocalRef(cls);
  g_jvm->DetachCurrentThread();
  return 0;
}

 

JNIEXPORT jint JNICALL Java_com_company_JNIDemo_intMethod
  (JNIEnv *env, jobject obj, jint num)
{
  g_obj = env->NewGlobalRef(obj);
  env->GetJavaVM(&g_jvm);

  CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

  return num * num;
}

此时,有必要确保Java那边的代码是多线程安全的!

posted @ 2013-11-02 20:18  avexer  阅读(232)  评论(0编辑  收藏  举报