•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);
}