•The JNI interface pointer(JNIEnv) isvalid only in the
current thread.
•Should another thread need to access theJava VM, it must first call
AttachCurrentThread
() toattach itself to the VM and obtain a JNI interface pointer.
•Once attached to the VM, a native threadworks just
like anordinary Java thread running inside a native method.
•The native thread remains attached to theVM until it calls
DetachCurrentThread
()todetach itself.
Java:
import java.lang.management.ManagementFactory;
class MyThread{
private static void fromJNI(int i){
System.out.print("Java---------->");
System.out.println(i);
}
public static void main(String args[]){
MyThread mt = new MyThread();
mt.setJNIEnv();
mt.mainThread();
}
//native methods
private native void mainThread();
private native void setJNIEnv();
static{
//First, we use java.lang.management.ManagementFactory to show the pid of java progress.
String name = ManagementFactory.getRuntimeMXBean().getName();
System.out.println("Progress id in Java \n\t"+name);
System.loadLibrary("MyThread");
}
}
C:
#include <jni.h>
#include "MyThread.h"
#include <iostream>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
using namespace std;
#define NUMTHREADS 5
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;
int sum=0;
void *thread_fun(void* arg)
{
long tid;
tid = (long) arg;
cout<<"Execute order="<<sum++<<endl;
cout<<"thread id="<<tid<<endl;
JNIEnv *env;
jclass cls;
jmethodID mid;
//Attach主线程
if(g_jvm->AttachCurrentThread((void**)&env, NULL) != JNI_OK)
{
printf("%s: AttachCurrentThread() failed", __FUNCTION__);
return NULL;
}
//找到对应的类
cls = env->GetObjectClass(g_obj);
if(cls == NULL)
{
printf("FindClass() Error.....");
goto error;
}
//再获得类中的方法
mid = env->GetStaticMethodID( cls, "fromJNI", "(I)V");
if (mid == NULL)
{
printf("GetMethodID() Error.....");
goto error;
}
//最后调用java中的静态方法
env->CallStaticVoidMethod(cls, mid ,(int)tid);
error:
//Detach主线程
if(g_jvm->DetachCurrentThread() != JNI_OK)
{
printf("%s: DetachCurrentThread() failed", __FUNCTION__);
}
sleep(30);
pthread_exit(0);
}
//Second
//由java调用以创建子线程
JNIEXPORT void JNICALL Java_MyThread_mainThread
(JNIEnv *env, jobject obj){
int i;
pthread_t pt[NUMTHREADS];
for (i = 0; i < NUMTHREADS; i++){
//创建子线程
//pthread_create(&pt[i], NULL, &thread_fun, (void*)i);
}
//Because the main thread exits. Put a sleep in the main thread.
//Or no result will be shown.
sleep(30);
/*
you can also try to use join
*/
}
//First
//由java调用来建立JNI环境
JNIEXPORT void JNICALL Java_MyThread_setJNIEnv
(JNIEnv *env, jobject obj){
//保存全局JVM以便在子线程中使用
env->GetJavaVM(&g_jvm);
//不能直接赋值(g_obj = obj)
g_obj = env->NewGlobalRef(obj);
}