2014-04-14 8 views
5

मैं एक पुराने जावा प्रोग्राम पर काम कर रहा हूं जिसमें फोर्ट्रान कॉल के साथ मूल पुस्तकालय शामिल है।देशी मेमोरी लीक देशी कोड

तो, मेरे पास जावा है जो जेएनआई के माध्यम से सी को कॉल करता है, और फिर फोरट्रान को कॉल करता है।

उत्पादन में हम जैसे स्मृति त्रुटि से बाहर है:

मूल निवासी स्मृति आबंटन (malloc) सी में jfloat के लिए 120000 बाइट्स आवंटित करने में विफल: \ BUILD_AREA \ jdk6_37 \ हॉटस्पॉट \ src \ शेयर \ वी एम \ prims \ jni.cpp

मुझे संदेह है कि यह एक स्मृति रिसाव है।

मैं कंपनी में नया हूं, और मैं लिनक्स पर काम करना चाहता हूं लेकिन वे मुझे विंडोज पर काम कर रहे हैं :( उत्पादन के तहत हम .so फ़ाइल का उपयोग कर रहे हैं क्योंकि हम सौर पर हैं, और मैं विंडोज़ पर डीएलएल का उपयोग करता हूं (तार्किक।)

सबसे पहले, मैंने उत्पादन समस्या को पुन: पेश करने की कोशिश की। इसलिए, मैंने एक यूनिट परीक्षण बनाया जो डीएलएल लोड करता है और जावा क्लास को कॉल करता है जो मूल विधि को कई बार कॉल करता है। जब मैंने ऐसा किया, मैंने देखा processExplorer.exe के साथ कि स्मृति 2 सेकंड तक 2 एमबी तक बढ़ी है। और मेरे पास उत्पादन में अपवाद है।

मुझे खुशी है कि मैंने सफलतापूर्वक समस्या का पुन: उत्पन्न किया, और मैं वें कह सकता था समस्या पर सी या फोरट्रान कोड से आया था।

इसके बाद, मैं फोरट्रान करने के लिए कॉल निकालने का प्रयास किया, और मेरे जावा केवल सी कहा जाता है (फोरट्रान के बिना, इस परीक्षण मुझे देखने के लिए अनुमति दी है, तो समस्या सी या फोरट्रान से आ रहा था।)

और परिणाम था कि स्मृति हिल नहीं गया! ठंडा! मैं कह सकता था कि मुझे सी

में malloc/free के साथ कोई समस्या नहीं थी इसलिए, मैंने कोड को देखने के लिए थोड़ा फोरट्रान सीखने का फैसला किया। :)

मैंने सीखा कि फोरट्रान में हम स्मृति के साथ खेलने के लिए आवंटित और कीवर्ड को आवंटित कर सकते हैं। और मेरे कोड में इन कीवर्ड शामिल नहीं हैं। :(

इस सब के बाद, किसी ने मुझे सोलारिस पर पहुँच मेरी JUnit परीक्षण शुरू करने के लिए दे कि कॉल जावा> JNI-> सी => फोरट्रान और DLL के बजाय .so उपयोग करने के लिए।

और आश्चर्य - स्मृति के लिए कदम नहीं था !!! मैं सोलारिस या RedHat के तहत किसी भी समस्या नहीं है

मैं अटक कर रहा हूँ क्योंकि समस्या उत्पादन पर मौजूद है, लेकिन मैं यह स्पष्ट रूप से पुन: पेश नहीं कर सकते :(

।।

मुझे डीएलएल और एसओ के बीच एक अंतर क्यों दिखता है? कोड (जावा/सी/फोरट्रान) बिल्कुल वही है क्योंकि यह मुझे संकलित करता है।

मैं और अधिक जांच कैसे कर सकता हूं?

मैंने खिड़कियों के नीचे मेमोरी डंप करने का प्रयास किया है जहां मैंने समस्या का पुनरुत्पादन किया, लेकिन मुझे कुछ भी दिखाई नहीं दे रहा है।

जेवीएम में समस्या है? या समस्या जेएनआई के माध्यम से सी को पारित वस्तु में हो सकती है?

इस समस्या के साथ मेरी मदद करने के लिए बहुत बहुत धन्यवाद।

जानकारी: मैं विंडोज 7 64bits

पुनश्च उपयोग कर रहा हूँ: मैं फ्रेंच हूँ, इसलिए मेरी अंग्रेजी बहाना। मैं हर बार अपना सर्वश्रेष्ठ करने की कोशिश करता हूं। ;)

यहाँ च सी कोड शीर्षक है:

JNIEXPORT jint JNICALL Java_TrtModlin_modlin_1OM 
    (JNIEnv * env, jobject obj, 
jfloatArray pmtPar, 
jobjectArray abaquePar, jobjectArray donPar, jfloatArray condPar, jobjectArray resPar, jintArray flagPar) 
    { 

कुछ कोड, और फोरट्रान

#ifndef unix 
     modlin_OM(pmt, abaque, don, cond, res, & iFlag) ; 
    #else 
modlin_om_(pmt, abaque, don, cond, res, & iFlag) ; 
    #endif 
के लिए विधि कॉल:

#ifndef unix 
     __MINGW_IMPORT void modlin_OM(float pmt[], float abaque[][], float don[][], float cond[], float res[][], int flag[]) ; 
    #else 
     extern void modlin_om_(float * pmt, float * abaque, float * don, float * cond, float * res, int * flag) ; 
    #endif 

और विधि के बाद

जैसा कि मैंने पहले कहा था, मैं इन पंक्तियों को हटाकर सी को कॉल का परीक्षण करता हूं और टी वह स्मृति नहीं बढ़ी :(मैं मुफ्त (कुछ वार) के साथ एक रेखा को हटाकर परीक्षण करता हूं और स्मृति बढ़ती है क्योंकि इस मामले में मुफ्त नहीं किया जाता है। यही कारण है कि मैंने निष्कर्ष निकाला कि मेरा सी फ्री/मॉलोक के साथ ठीक था।

+1

और क्या आपके पास दोनों प्लेटफार्मों (यूनिक्स और विंडोज) के लिए उन सी बाइंडिंग का स्रोत है? – fge

+0

हाँ मेरे पास स्रोत है लेकिन यह विंडोज़ या यूनिक्स के लिए समान है, मैं इसे अपने प्रश्न के अंत में जोड़ता हूं (यदि आप सभी स्रोत चाहते हैं, तो मैं आपको दे सकता हूं अगर आप चाहें) –

+0

कौन सा किलर कंपाइलर? – Peter

उत्तर

1

एक स्मृति समस्या का विश्लेषण हमेशा जटिल होता है। मेरे अनुभव से दो तरीके हैं:

1) आप पुन: उत्पन्न करने का प्रयास करते हैं। यह मानता है कि आपके पास स्रोत कोड और मूल कारण का विचार है। 2) आप उत्पादन क्रैश का निरीक्षण करते हैं: आवृत्ति, अन्य घटनाओं के साथ सहसंबंध, आदि

यह यह निर्धारित करने में मदद कर सकता है कि यह एक स्मृति रिसाव है या नहीं (यह एक व्यापार भार के तहत एक उच्च उपभोग हो सकता है .. ।)

अपने विशेष मामले में, मैं निम्नलिखित बातों पर ध्यान:

  1. कोड का व्यवहार भिन्न ओएस पर अलग अलग हो सकता है। जावा कोड (जेवीएम बग) के लिए यह बहुत दुर्लभ है। यह मूल कोड के साथ अक्सर होता है (उदाहरण के लिए, ज़िप को बंद करना भूल जाता है, लिनक्स पर एक स्मृति रिसाव का कारण बनता है लेकिन विंडोज़ पर नहीं ...)

  2. आपके सी हेडर (* .h) में: abaque, don और res विंडोज़ पर 'फ्लोट * *' और यूनिक्स पर 'फ्लोट *'। यह अपने सी हेडर में एक बग हो सकता है, या तो इसका मतलब सी कार्यान्वयन ऑपरेटिंग सिस्टम के आधार एक ही तर्क प्रकारों की उम्मीद नहीं है (जो मेरे लिए अजीब है ...)

दूसरे मामले में, तथ्य यह है कि आप विंडोज़ पर अपने सी हेडर संकलित करते हैं (यह लक्ष्य नहीं है) आपको समझा सकता है कि आप सही जेएनआई स्टब्स (सामान्य क्रॉस-संकलन समस्या) उत्पन्न नहीं करते हैं ... यहां से हम कई मान्यताओं, सरल या बहुत जटिल बना सकते हैं ..

शुभकामनाएँ!

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