2009-08-27 11 views
6

का उपयोग कर जावा से कोड को कॉल करते समय मेमोरी रिसाव मेरे पास एक सी प्रोग्राम है जो जेएनआई का उपयोग करके जावा स्टोर में कुछ ऑब्जेक्ट स्टोर करता है। (किसी से पूछने से पहले, जावा स्टोर का उपयोग करना एक आवश्यकता है और मुझे सी में एक क्लाइंट लिखना है जो इस स्टोर से ऑब्जेक्ट्स को जोड़ने और पुनर्प्राप्त करने में सक्षम होगा)।जेएनआई

मैंने प्रोग्राम बनाया और आकार 1KB के 100000 ऑब्जेक्ट को जोड़ने की कोशिश की। लेकिन केवल 50000 ऑब्जेक्ट्स जोड़ने के बाद मुझे 'मेमोरी से बाहर' संदेश मिल रहे हैं (कृपया ध्यान दें कि जब भी मैं नई स्ट्रिंग या बाइट सरणी को न्यूस्ट्रिंगटएफ और न्यूबाइटएरे फ़ंक्शन का उपयोग करके आवंटित करने में असमर्थ हूं, तो मैं इन्हें 'स्मृति से बाहर' संदेशों को प्रिंट कर रहा हूं)। उस समय मेरा आवेदन केवल 80 एमबी मेमोरी का उपयोग कर रहा है। मैं नहीं करता कि ये विधियां क्यों न लौट रही हैं। क्या मैं कुछ छोड़ रहा हूं।

इसके अलावा, स्मृति बढ़ती रहती है भले ही मैं बाइट सरणी और जावा के लिए बनाई गई स्ट्रिंग जारी कर रहा हूं।

यहां स्रोत कोड है।

void create_jvm(void) 
{ 
    JavaVMInitArgs vm_args;  
    JavaVMOption vm_options; 

    vm_options.optionString = "-Djava.class.path=c:\\Store"; 
    vm_args.version = JNI_VERSION_1_4; 
    vm_args.nOptions = 1; 
    vm_args.options = &vm_options; 
    vm_args.ignoreUnrecognized = 0; 

    JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 

    if(env != null) 
    { 
     j_store = (*env)->FindClass(env, "com/store"); 
     if(j_store == null) 
     { 
      printf("unable to find class. class name: JStore"); 
     }  
    } 
} 

void add(char* key, char* value, int length) 
{ 
    jstring j_key = (*env)->NewStringUTF(env, key); 
    jbyteArray j_value = (*env)->NewByteArray(env, length); 

    (*env)->SetByteArrayRegion(env, j_value, 0, length, (jbyte *)value); 
    ret = (*env)->CallStaticBooleanMethod(env, j_store, method_id, j_key, j_value); 

    if(j_value != null) 
    { 
     (*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, 0); 
    } 
    if(j_key != null) 
    { 
     (*env)->ReleaseStringUTFChars(env, j_key, key); 
    } 
} 

जावा पक्ष बाइट [] में डेटा प्राप्त करता है और इसे एक हैशटेबल में संग्रहीत करता है। मुद्दा यह है कि हर बार जब कोड मेमोरी चलाता है तो केवल जोड़ता है और कभी जारी नहीं होता है। मैंने 1 एमबी ऑब्जेक्ट जोड़ने और इसे डीबग करने का प्रयास किया।

जब मैं न्यूबेटएरे को कॉल करता हूं तो प्रक्रिया मेमोरी 1 एमबी तक बढ़ जाती है। लेकिन जब CallStaticBooleanMethod को प्रक्रिया मेमोरी 4 एमबी तक बढ़ाया जाता है। और रिलीजबेटएरे ऐलेमेंट्स को कॉल किसी भी मेमोरी को रिलीज़ नहीं करता है।

मैं इस के बाद एक और 1 एमबी वस्तु जोड़ते हैं, तो इस प्रक्रिया को स्मृति ही रहता है जब मैं NewByteArray फोन और यह 1 एमबी की वृद्धि जब मैं CallStaticBooleanMethod फोन लेकिन एक ही रहता है जब मैं बाइट सरणी जारी करने के लिए प्रयास करें।

उत्तर

17

जब आप नया ... फ़ंक्शन कहते हैं, तो आप स्थानीय स्टैक फ्रेम में इस ऑब्जेक्ट का संदर्भ "स्थानीय संदर्भ" बनाते हैं। यह जावा ऑब्जेक्ट को जीसी से इस ऑब्जेक्ट को रोकता है जबकि आपको अभी भी इसकी आवश्यकता होती है। यह ठीक है अगर आप कुछ मूल विधि को कार्यान्वित कर रहे हैं - इसका स्थानीय फ्रेम केवल विधि कॉल अवधि के लिए बनाया गया है। लेकिन जब आप मूल जावा-संलग्न धागे से ऑब्जेक्ट बना रहे हैं, तो यह इस थ्रेड स्टैक फ्रेम से बाध्य हो जाता है, जो केवल इस थ्रेड के साथ नष्ट हो जाएगा।

तो, जब आप किसी ऑब्जेक्ट के साथ करते हैं तो आप इसे हटाने के लिए DeleteLocalRef() पर कॉल कर सकते हैं। या आप अपनी अवधि के लिए एक अलग स्थानीय फ्रेम बनाने के लिए पुशलोकलफ्रेम()/पॉपलोकलफ्रेम() की जोड़ी के साथ पूरे ऐड() फ़ंक्शन को घेर सकते हैं।

+0

आपका मतलब है कि नए कार्यों का उपयोग करके मुझे जो भी संसाधन मिल रहा है, मैं DeleteLocalRef() का उपयोग कर जीसी के लिए रिलीज़ कर सकता हूं। कुछ इस तरह। jstring j_key = (* env) -> NewStringUTF (env, key); jbyteArray j_value = (* env) -> न्यूबीटएरे (एनवी, लंबाई); .. .. ... (* env) -> DeleteLocalRef (j_key); (* env) -> DeleteLocalRef (j_value); – ata

+2

हां, यह जेनी को बताता है कि सी कोड को इस संसाधन को जारी किया गया है - यदि जावा के पास इसका संदर्भ नहीं है, तो यह जीसी – Xeor

+0

के लिए नि: शुल्क हो जाता है रिलीजस्ट्रिंगटफिशर और अन्य रिलीज फ़ंक्शंस का उद्देश्य क्या है? जहां तक ​​मैंने प्रलेखन पढ़ा है, यह बताता है कि यह इंगित करता है कि आपको अब संसाधन की आवश्यकता नहीं है, और इसे मुक्त किया जाना चाहिए। मुझे लगता है कि मूल कार्यों (जावा से सी) के लिए तब तक दूसरी तरफ नहीं था। – ata

4

फ़ंक्शंस का उद्देश्य रिलीजबेटएरेरेइमेंट्स और रिलीजस्ट्रिंगटफ़ाफ़रर्स ऑब्जेक्ट को मिटाना नहीं है, लेकिन GetByteArrayElements या GetStringUTFChars के साथ पॉइंटर प्राप्त करने के बाद इसे अनलॉक करने के लिए है। दो अगर कथन हटा दिए जाने चाहिए।

+0

मैंने इन दो बयानों को हटा दिया है लेकिन इससे कोई फर्क नहीं पड़ता। अजीब चीज यह है कि जावा विधि को कॉल करते समय स्मृति उपयोग 2 एमबी से 4 एमबी (1 एमबी ऑब्जेक्ट जोड़ते समय) बढ़ता है। ऐसा लगता है कि बाइट एरे कहीं और नकल कर रहे हैं और कभी कचरा इकट्ठा नहीं किया जाता है? – ata

+0

जावा विधि में क्या हो रहा है? –

+0

कोड थोड़ा सा सामान्य है। हालांकि मैं एक बाइट [] में गुजर रहा हूं, मान पहले क्रमबद्ध है और फिर हैशटेबल में सहेजा गया है। आप चाहते हैं कि मैं जावा कोड भी पोस्ट करूं? (सीरियलाइजेशन आवश्यकता का हिस्सा है क्योंकि डेटा हमेशा बाइट [] रूप में नहीं हो सकता है और डिस्क पर या किसी अन्य प्रक्रिया में संग्रहीत किया जा सकता है) – ata

0

हां, मैं एक ही मुद्दे से मुलाकात की।

मेरा जावा एप्लिकेशन जेएनआई द्वारा सी ++ एप्लिकेशन को कॉल करता है, सी ++ एप्लिकेशन एक नया धागा शुरू करेगा, और जावा विधि को वापस कॉल करेगा। नए धागे में, कई ऑब्जेक्ट्स बनाए गए थे और मेमोरी तेज़ी से बढ़ी, हालांकि मैंने डिलीटोकोकलफ, पुशलोकलफ्रेम और पॉपलोकलफ्राम का उपयोग किया।

मुझे न्यू ऑब्जेक्ट विधि द्वारा बनाई गई कई ऑब्जेक्ट्स को रिलीज़ नहीं किया जा सकता है। यह बहुत अजीब है ।

+0

नया पाया गया, यदि कॉल सी ++ विधि में कॉल में बड़ी स्ट्रिंग (प्रिंटिंग/भेजना/गुजरना) है, तो स्मृति जल्दी बढ़ जाती है, फिर बाद में बहती है – Walter

0

मैंने कोशिश की, आप सभी ने कहा।

किसी भी jstring के निर्माण के बाद DeleteLocalRef विधि का उपयोग करना चाहिए और अब और उपयोग नहीं करना चाहिए।

न्यूxxएक्स या CallStaticObjectMethod jstring बना सकता है, इसे सभी को हटाना होगा।

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