1. 程式人生 > >[Java] [ Android ] [ JNI ] [ Native執行緒程式設計中使用JavaVM->AttachCurrentThread獲取JNIEnv以訪問Java層物件]

[Java] [ Android ] [ JNI ] [ Native執行緒程式設計中使用JavaVM->AttachCurrentThread獲取JNIEnv以訪問Java層物件]

簡介

由JVM的執行緒棧的設計,JNI程式設計必須遵守如下原則
• JNIEnv結構與執行緒繫結的,絕對不能在多執行緒中共享JNIEnv結構
• LocalRef與本執行緒繫結的,絕對不能在多執行緒中共享LocalRef

Native執行緒程式設計中使用JavaVM->AttachCurrentThread獲取JNIEnv以訪問Java層物件

A JNI interface pointer (JNIEnv*) is passed as an argument for each native
function mapped to a Java method, allowing for interaction
with the JNI environment within the native method.This JNI interface
pointer can be stored, but remains valid only in the current thread.
Other threads must first call AttachCurrentThread()to attach
themselves to the VM and obtain a JNI interface pointer. Once
attached, a native thread works like a regular Java thread running
within a native method. The native thread remains attached to the VM
until it callsDetachCurrentThread() to detach itself.[3]

因此,在Native執行緒中,需要通過JavaVM->AttachCurrentThread獲取JNIEnv,再由JNIEnv去訪問Java層類及物件。
JavaVM在Navtive中具有唯一例項,可通過全域性變數儲存

JavaVM *jvm; /* already set */
f()
{
  JNIEnv *env;
  (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
  ... /* use env */
}

如上,只要jvm被賦值,就可通過AttachCurrentThread得到JNIEnv。
JavaVM結構可以在多執行緒間共享,有以下兩個jvm的賦值時機:
• JNI_GetCreatedJavaVM建立虛擬機器時
• JNI_OnLoad
此外,只要在該執行緒中事先呼叫過AttachCurrentThread後,JNIEnv->GetEnv可以返回JNIEnv。