2012-09-14 9 views
27

मैं एक वैश्विक में JNIEnv बंद भंडारण कर रहा हूँ तो मैं स्थिर जावा तरीकों बाद में कॉल कर सकते हैं करने के लिए एक वैश्विक संदर्भ में रखते हुए। लेकिन यह nessasary JNIEnv करने के लिए एक वैश्विक सूचक बंद स्टोर करने के लिए, वे जिस तरह से एक किसी अन्य जावा वस्तु के साथ होता है, या यह एक विशेष मामला है कि इस की आवश्यकता नहीं है है।JNIEnv पर्यावरण

JNIEnv* globalEnvPointer; 

[JNICALL etc] void init(JNIENv* env, [etc]) 
{ 
    //required? 
    globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env); 
    //or is this OK? 
    globalEnvPointer = env; 
} 

संपादित

मैं थोड़ा यहाँ गूंगा बिंग रहा हूँ, सभी तरीकों कि globalEnvPointer का उपयोग करेगा, मेरी init भीतर लागू कर रहे हैं, क्योंकि मेरी init वास्तव में मेरे c कार्यक्रम के main विधि है, जो जीता है ' कार्यक्रम के अंत तक वापस आते हैं। मैं सी कार्यक्रम में कोई अन्य धागे का भी उपयोग नहीं कर रहा हूं। मुझे लगता है कि यह जवाब को सरल बनाता है।

JNIEnv* globalEnvPointer; 

[JNICALL etc] void main(JNIENv* env, [etc]) 
{ 
    //required? 
    globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env); 
    //or is this OK? 
    globalEnvPointer = env; 
    someMethod(); 
} 

void someMethod() 
{ 
    //use globalEnvPointer here 
} 

उत्तर

41

आप JNIEnv पॉइंटर को कैश नहीं कर सकते हैं। इसके बारे में here:

जेएनआई इंटरफ़ेस पॉइंटर (जेएनआईएनएनवी) केवल वर्तमान धागे में मान्य है। एक और धागा जावा वी एम का उपयोग करने की आवश्यकता हुई है, यह पहली बार AttachCurrentThread() वी एम को ही देते हैं और एक JNI इंटरफ़ेस सूचक प्राप्त करने के लिए कॉल करना होगा। एक बार वीएम से जुड़ा हुआ होने पर, मूल धागा एक सामान्य विधि के अंदर चलने वाले सामान्य जावा थ्रेड की तरह काम करता है। जब तक यह DetachCurrentThread() को अलग करने के लिए कॉल नहीं करता है तब तक मूल धागा वीएम से जुड़ा रहता है।

आप क्या कर सकते हैं JavaVM पॉइंटर को कैश करना है।

static JavaVM *jvm; 

[JNICALL etc] void init(JNIENv* env, [etc]) 
{ 
    jint rs = (*env)->GetJavaVM(env, &jvm); 
    assert (rs == JNI_OK); 
} 

और फिर जब भी आप तो एक संदर्भ में, जहां यह नहीं दिया जाता है तो आप इस करते हैं से JNIEnv सूचक की जरूरत है:

void someCallback() { 
    JNIEnv *env; 
    jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); 
    assert (rs == JNI_OK); 
    // Use the env pointer... 
} 

लेकिन जब भी आप का उपयोग करने के env सूचक जावा से एक देशी विधि कॉल दिया जाता है :

JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) { 
    // just use the env pointer as is. 
} 
+0

यह सब एक धागा, कि एक फर्क पड़ता है क्या है? यानी मेरा 'init' उसी धागे में बुलाया जाता है क्योंकि बाद में स्थिर जावा विधियों को कॉल किया जाएगा। – weston

+0

हमेशा 'JNIEnv' सूचक है कि सी समारोह में में आ रहा है का उपयोग करें। जैसा कि मेरे आखिरी उदाहरण में है। – maba

+0

कृपया अपने उदाहरण में मेरे संपादन देखने के लिए, यदि 'Java_package_Class_method' बुलाया' someCallback', आप के माध्यम से जाने की जरूरत नहीं होगी 'JavaVM' क्या तुम करोगी? असल में यह मैं कर रहा हूं, सिर्फ 'कुछ कॉलबैक' को पास करने के बजाय वैश्विक का उपयोग कर रहा हूं। – weston

संबंधित मुद्दे