के रूप में दूसरों को पहले से ही समस्याओं के बिना लिखा
- आप एक स्थिर सी ++ चर में
jmethodID
स्टोर कर सकते हैं
- आप
jobject
या एक स्थिर सी ++ चर में jclass
env->NewGloablRef()
फोन करके वैश्विक वस्तुओं के लिए उन्हें परिवर्तित करने के बाद स्थानीय स्टोर कर सकते हैं
मैं सिर्फ एक अतिरिक्त जानकारी जोड़ना चाहता हूं: एक स्थिर सी ++ परिवर्तनीय वाई में jclass को संग्रहीत करने का मुख्य कारण हो सकता है कि आपको लगता है कि यह हर बार env->FindClass()
पर कॉल करने के लिए एक प्रदर्शन समस्या है।
लेकिन मैं गति FindClass()
की विंडोज पर QueryPerformanceCounter()
एपीआई के साथ एक प्रदर्शन काउंटर के साथ मापा। एक 3,6 गीगा सीपीयू के साथ अपने कंप्यूटर
jcass p_Container = env->FindClass("java/awt/Container");
के निष्पादन 0,01 एमएस और 0,02 एमएस के बीच लेता है पर
: और परिणाम आश्चर्यजनक था। यह अविश्वसनीय रूप से तेज़ है। मैंने जावा स्रोत कोड में देखा और वे एक शब्दकोश का उपयोग करते हैं जहां कक्षाएं संग्रहीत की जाती हैं। ऐसा लगता है कि यह बहुत ही कुशलतापूर्वक लागू किया गया है।
मैं कुछ और अधिक कक्षाओं का परीक्षण किया और यहाँ परिणाम है:
Elapsed 0.002061 ms for java/net/URL
Elapsed 0.044390 ms for java/lang/Boolean
Elapsed 0.019235 ms for java/lang/Character
Elapsed 0.018372 ms for java/lang/Number
Elapsed 0.017931 ms for java/lang/Byte
Elapsed 0.017589 ms for java/lang/Short
Elapsed 0.017371 ms for java/lang/Integer
Elapsed 0.015637 ms for java/lang/Double
Elapsed 0.018173 ms for java/lang/String
Elapsed 0.015895 ms for java/math/BigDecimal
Elapsed 0.016204 ms for java/awt/Rectangle
Elapsed 0.016272 ms for java/awt/Point
Elapsed 0.001817 ms for java/lang/Object
Elapsed 0.016057 ms for java/lang/Class
Elapsed 0.016829 ms for java/net/URLClassLoader
Elapsed 0.017807 ms for java/lang/reflect/Field
Elapsed 0.016658 ms for java/util/Locale
Elapsed 0.015720 ms for java/lang/System
Elapsed 0.014669 ms for javax/swing/JTable
Elapsed 0.017276 ms for javax/swing/JComboBox
Elapsed 0.014777 ms for javax/swing/JList
Elapsed 0.015597 ms for java/awt/Component
Elapsed 0.015223 ms for javax/swing/JComponent
Elapsed 0.017385 ms for java/lang/Throwable
Elapsed 0.015089 ms for java/lang/StackTraceElement
ऊपर मूल्यों जावा घटना डिस्पैचर धागे से कर रहे हैं। यदि मैं एक देशी कोड को उसी कोड को निष्पादित करता हूं जो मेरे द्वारा CreateThread()
द्वारा बनाया गया है, तो यह भी 10 गुना तेज चलाता है। क्यूं कर?
तो यदि आप FindClass()
पर अक्सर कॉल नहीं करते हैं तो बहुत अधिक समस्या नहीं होती है जब वैश्विक संदर्भ बनाने और इसे स्थिर चर में संग्रहीत करने के बजाय आपके जेएनआई फ़ंक्शन को कॉल किया जाता है।
एक अन्य महत्वपूर्ण विषय धागा सुरक्षा है। जावा में प्रत्येक थ्रेड की अपनी स्वतंत्र JNIEnv
संरचना होती है।
- वैश्विक
jobject
या jclass
किसी भी जावा सूत्र में मान्य हैं।
- स्थानीय ऑब्जेक्ट केवल कॉलिंग थ्रेड के
JNIEnv
में एक फ़ंक्शन कॉल में मान्य हैं और जब जेएनआई कोड जावा पर वापस आता है तो कचरा इकट्ठा होता है।
अब यह सूत्र है कि आप प्रयोग कर रहे हैं पर निर्भर करता है: आप env->RegisterNatives()
के साथ अपने सी ++ समारोह रजिस्टर और जावा कोड अपने JNI कार्यों में बुला रहा है तो आप सभी वस्तुओं की दुकान चाहिए, जिसे आप बाद में उपयोग करने के लिए, वैश्विक रूप में चाहते हैं वस्तुओं को अन्यथा वे कचरा इकट्ठा करेंगे।
लेकिन अगर आप CraeteThread()
एपीआई (Windows पर) के साथ अपने स्वयं धागा बना सकते हैं और AttachCurrentThreadAsDaemon()
फोन करके JNIEnv
संरचना प्राप्त तो पूरी तरह से अन्य नियम लागू होंगे: यह अपने स्वयं के धागे, कि कभी नहीं जावा, कचरा करने के लिए नियंत्रण देता है कलेक्टर कभी भी आपके थ्रेड पर बनाए गए ऑब्जेक्ट्स को साफ़ नहीं करेगा और आप बिना किसी समस्या के स्थिर सी ++ चर में स्थानीय ऑब्जेक्ट्स स्टोर भी कर सकते हैं! (लेकिन इन्हें अन्य धागे से नहीं पहुंचा जा सकता है) इस मामले में यह बेहद जरूरी है कि आप अपने सभी स्थानीय उदाहरण मैन्युअल रूप से env->DeleteLocalRef()
के साथ साफ़ करें अन्यथा आपको स्मृति रिसाव होगा।
मैं दृढ़ता से सभी स्थानीय वस्तुओं को एक रैपर वर्ग में लोड करने की अनुशंसा करता हूं जो DeleteLocalRef()
को इसके विनाशक में कॉल करता है। मेमोरी लीक से बचने के लिए यह एक बुलेट प्रूफ तरीका है।
विकास JNI कोड बहुत बोझिल हो सकता है और आप दुर्घटनाओं है कि आप समझ में नहीं आता हो सकता है।
java -Xcheck:jni -jar MyApplication.jar
तो आप क्या समस्याओं JNI कोड में हुआ है देखेंगे: एक दुर्घटना के कारण एक डॉस विंडो खोलें और निम्न आदेश के साथ अपने जावा आवेदन शुरू जानने के लिए।
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6e8655d5, pid=4692, tid=4428
#
etc...
JNI स्वचालित रूप से स्थानीय 'द्वारा लौटाए गए संदर्भों को साफ:
और आपको लगता है कि जावा जहां JAR फ़ाइल है एक ही फ़ोल्डर में बनाता है लॉग फ़ाइल में स्टैकट्रेस मिलेगा: उदाहरण के लिए जावा पक्ष पर वापस जाने पर FindClass'। –
इस प्रकार, 'अधिकतर'। इस लिंक में – bmargulies
(http://java.sun.com/docs/books/jni/html/other.html), वे NewWeakGlobalRef का उपयोग करते हैं। मैं कमजोर संदर्भ के साथ कोशिश करेंगे। – YuppieNetworking