2009-06-18 20 views
9

मैंने सोचा होगा इस सवाल से पहले कहा गया है, लेकिन मैं इसे यहाँ नहीं मिला ...फोर्स जावा मेरी सी ++ नाशक (JNI) कॉल करने के लिए

मैं एक के चारों ओर एक JNI आवरण बनाने के लिए बड़ा घूँट का उपयोग किया है सी ++ कक्षा। सभी महान काम करता है सिवाय इसके कि जावा क्लास के अंतिमकरण() को कभी भी कॉल नहीं करता है, इसलिए बदले में, मेरी कक्षा के विनाशक को कभी भी बुलाया नहीं जाता है। कक्षा का विनाशक कुछ अंतिम फ़ाइल I/O करता है, इसलिए दुर्भाग्यवश, यह केवल मामूली स्मृति रिसाव नहीं है।

Google के माध्यम से खोजना, जावा को जीसी को मजबूर करने और किसी ऑब्जेक्ट को नष्ट करने का कोई तरीका प्रतीत नहीं होता है। सच?

मुझे पता है कि मैं अपनी एसडब्ल्यूआईजी फ़ाइल में हेरफेर कर सकता हूं और एक जावा फ़ंक्शन बना सकता हूं जो सी ++ विनाशक को कॉल करेगा, लेकिन इस वर्ग का उपयोग कई उपयोगकर्ताओं द्वारा कई अलग-अलग प्लेटफ़ॉर्म/भाषाओं में किया जाता है, इसलिए केवल जावा के अतिरिक्त ही एक असंगतता कि हमारे तकनीकी लेखकों को पसंद नहीं है।

उत्तर

7

आप सिस्टम.gc() के साथ जीसी को मजबूर नहीं कर सकते हैं। यह भी गारंटी नहीं है कि उदाहरण के लिए कोई जीसी रन कभी भी होगा यदि आपका ऐप केवल थोड़े समय के लिए चलता है और फिर आपका फ़ाइनलाइज़र बिल्कुल नहीं चलता है (JVM इसे बाहर निकलने पर नहीं चलाता है)। आपको अपनी कक्षा के लिए एक करीबी() या नष्ट() या जो कुछ भी फ़ंक्शन बनाना चाहिए और जब आप इस कक्षा के उदाहरण का उपयोग करके समाप्त कर लें, तो इसे अंततः अंततः ब्लॉक से, जैसे।


MyClass x = null; 
try{ 
    x = new MyClass(); 
    x.work(); 
} finally { 
    if (x!=null) 
     x.close(); 
} 
5

जावा फाइनलाइजर्स ज्यादातर मेरी बेकार हैं, और निश्चित रूप से सी ++ विनाशकों के प्रतिस्थापन नहीं हैं। दुर्भाग्यवश, जावा के पास C++ RAII के लिए कोई प्रतिस्थापन नहीं है।

जावा अंतिमकरण को मजबूर करने की कोशिश करने से परेशान न करें। जब आप जो कुछ भी कर रहे हैं, उसके साथ सभी कार्यवाही करेंगे। यह सब आप कर सकते हैं।

0

मुद्दे इस तरह कारण सी # नियतात्मक अंतिम रूप दिए जाने के लिए IDisposable पैटर्न चुना है।

मेरा सुझाव है कि आप एक ही पैटर्न का पालन करें और इसे अपने जावा उपयोगकर्ताओं के लिए अनुकूलित करें।

अपनी सी ++ कक्षा में, एक अलग, सार्वजनिक विधि बनाएं जो आपके संसाधनों का निपटान करे। इसे बंद करें, या निपटान करें, या कुछ।

क्या आपका सी ++ विनाशक सार्वजनिक विधि को कॉल करता है, और सी ++ कक्षा के प्रबंधित/जीसी उपयोगकर्ताओं को बताता है कि उन्हें मेमोरी लीक से बचने के लिए विधि को कॉल करना होगा।

5

यदि आप किसी निश्चित समय पर चलाने के लिए finalize विधि में कोड पर भरोसा कर रहे हैं, तो आपको अपने दृष्टिकोण पर पुनर्विचार करना होगा। यहां समस्या यह है कि आपको नहीं पता कि finalize को JVM द्वारा कॉल किया जाएगा, क्योंकि आप नहीं जानते कि ऑब्जेक्ट कब कचरा होगा।

एक बात जो आपको विचार करनी चाहिए, क्योंकि आपकी कक्षा का पुन: उपयोग अन्य परियोजनाओं में किया जाएगा, यह संभव है कि एक अंत उपयोगकर्ता एक वर्ग के उदाहरण का उपयोग इस तरह से कर सके कि इसे एकत्र नहीं किया जाएगा या कचरा संग्रह संभव नहीं होगा, जैसे वर्ग के एक उदाहरण के लिए एक स्थिर संदर्भ बनाना। मुझे लगता है कि close या destroy विधि बनाना यह सुनिश्चित करने के लिए आपकी सबसे सुरक्षित शर्त है कि संसाधन आपके जावा ऑब्जेक्ट से जुड़े सी ++ वर्ग का उदाहरण उचित रूप से जारी किए जाते हैं।

के बाद फिर से उपयोग एक चिंता का विषय है, तो आप सी ++ नाशक जांच को देखने के लिए हो सकता था अगर संसाधन जारी किया गया था और इतने की तरह अगर वे नहीं था एक ही कोड कॉल करने के लिए,:

class MyThing { 
    public: 
    void close(); 
    ~MyThing(); 

    private: 
    bool released = false; 
}; 

void 
MyThing::close() { 
    // close logic here 
    this->released = true; 
} 

MyThing::~MyThing() { 
    if (!released) { 
    this->close(); 
    } 
} 

इस तरह, आपके मौजूदा सी ++ कोड को उम्मीद में ज्यादा बदलाव नहीं करना पड़ेगा, और आप यह सुनिश्चित कर सकते हैं कि आपके संसाधन जेएनआई के माध्यम से चल रहे देशी कोड के संदर्भ में निर्धारित निर्धारक तरीके से जारी किए जाएं।

3

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

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