當JNI遇到多線程--java對象如何被C++中的多個線程訪問?
java中要訪問C++代碼時, 使用JNI是唯一選擇. 然而,在多線程的情況下, 可能出現(xiàn)以下問題:
問題描述:
一個java對象通過JNI調(diào)用DLL中一個send()函數(shù)向服務(wù)器發(fā)送消息,不等服務(wù)器消息到來就立即返回.同時
把JNI接口的指針JNIEnv *env,和jobject obj保存在DLL中的變量里.
一段時間后,DLL中的消息接收線程接收到服務(wù)器發(fā)來的消息,
并試圖通過保存過的env和obj來調(diào)用先前的java對象的方法來處理此消息.
然而,JNI文檔上說,JNI接口的指針JNIEnv*不能在c++的線程間共享,
在我的程序中,如果接收線程試圖調(diào)用java對象的方法,程序會突然退出.
不知道有沒有方法突破JNI接口的指針不能在多個c++線程中共享的限制?
解決辦法:
在?http://java.sun.com/docs/books/jni/html/pitfalls.html#29161?提到,
JNI接口指針不可為多個線程共用,但是java虛擬機的JavaVM指針是整個jvm公用的. 于是,在DLL中可以調(diào)用:
static JavaVM* gs_jvm;
env->GetJavaVM(&gs_jvm); //來獲取JavaVM指針.獲取了這個指針后,在DLL中的另一個線程里,可以調(diào)用:
JNIEnv *env;
gs_jvm->AttachCurrentThread((void **)&env, NULL);
(1)
//java代碼:Test.java:
import java.io.*;
class Test implements Runnable
{
public int value = 0;
private Thread tx=null;
public Test()
{
tx=new Thread(this,"tx");
}
static
{
System.loadLibrary("Test");
}
public native void setEnev();
public static void main(String args[])
{
Test t = new Test();
t.setEnev();
System.out.println("ok in java main");
t.tx.start();
try
{
Thread.sleep(10000000);
}catch(Exception e)
{
System.out.println("error in main");
}
}
public void run()
{
try
{
while(true)
{
Thread.sleep(1000);
System.out.println(value);
}
}catch(Exception e)
{
System.out.println("error in run");
}
}
}
(2)
//DLL代碼:Test.cpp:
#include "test.h"
#include
#include
static JavaVM *gs_jvm=NULL;
static jobject gs_object=NULL;
static int gs_i=10;
void WINAPI ThreadFun(PVOID argv)
{
JNIEnv *env;
gs_jvm->AttachCurrentThread((void **)&env, NULL);
jclass cls = env->GetObjectClass(gs_object);
jfieldID fieldPtr = env->GetFieldID(cls,"value","I");
while(1)
{
Sleep(100);
//在DLL中改變外面的java對象的value變量的值.
env->SetIntField(gs_object,fieldPtr,(jint)gs_i++);
}
}
JNIEXPORT void JNICALL Java_Test_setEnev(JNIEnv *env, jobject obj)
{
printf("come into test.dll/n");
//Returns “0” on success; returns a negative value on failure.
int retGvm=env->GetJavaVM(&gs_jvm);
//直接保存obj到DLL中的全局變量是不行的,應(yīng)該調(diào)用以下函數(shù):
gs_object=env->NewGlobalRef(obj);
HANDLE ht=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFun,0,NULL,NULL);
printf("the Handle ht is:%d/n",ht);
}
C++ Java 任務(wù)調(diào)度
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。