नमस्ते!

मुझे लगता है कि आपको बहुत आश्चर्य नहीं होगा अगर मैं आपको बताऊं कि आपके कंप्यूटर में सीमित मात्रा में मेमोरी है :) यहां तक ​​कि एक हार्ड ड्राइव - आमतौर पर रैम स्टोरेज से कई गुना बड़ी - को आपके पसंदीदा गेम, टीवी शो, के साथ क्षमता से पैक किया जा सकता है। और अधिक। ऐसा होने से रोकने के लिए, आपको मेमोरी की वर्तमान स्थिति पर नज़र रखनी होगी और अपने कंप्यूटर से अनावश्यक फ़ाइलों को हटाना होगा। जावा प्रोग्रामिंग का इस सब से क्या लेना-देना है? सब कुछ! आखिरकार, जब जावा मशीन कोई वस्तु बनाती है, तो वह उस वस्तु के लिए मेमोरी आवंटित करती है।

एक वास्तविक बड़े कार्यक्रम में, दसियों और सैकड़ों-हजारों वस्तुएं बनाई जाती हैं, और उनमें से प्रत्येक के पास इसके लिए आवंटित स्मृति का अपना टुकड़ा होता है। लेकिन आपको क्या लगता है कि ये सभी वस्तुएं कब तक मौजूद हैं? क्या वे पूरे समय "जीवित" हैं जब हमारा कार्यक्रम चल रहा है? बिल्कुल नहीं। जावा वस्तुओं के सभी लाभों के साथ भी, वे अमर नहीं हैं :) वस्तुओं का अपना जीवनचक्र होता है। आज हम कोड लिखने से थोड़ा ब्रेक लेंगे और इस प्रक्रिया को देखेंगे :) इसके अलावा, यह आपकी समझ के लिए बहुत महत्वपूर्ण है कि कोई प्रोग्राम कैसे काम करता है और संसाधनों का प्रबंधन कैसे किया जाता है। तो, किसी वस्तु का जीवन कब शुरू होता है? एक व्यक्ति की तरह - अपने जन्म से, अर्थात सृजन से।


Cat cat = new Cat(); // Here the lifecycle of our Cat object begins!

सबसे पहले, जावा वर्चुअल मशीन ऑब्जेक्ट बनाने के लिए आवश्यक मात्रा में मेमोरी आवंटित करती है। फिर यह उस स्मृति का संदर्भ बनाता है। हमारे मामले में, उस संदर्भ को कहा जाता है cat, इसलिए हम उसका ट्रैक रख सकते हैं। फिर इसके सभी वेरिएबल्स को इनिशियलाइज़ किया जाता है, कंस्ट्रक्टर को कॉल किया जाता है, और — टा-दा! - हमारी नव-निर्मित वस्तु अपना जीवन जी रही है :)

वस्तुओं का जीवनकाल अलग-अलग होता है, इसलिए हम यहां सटीक संख्या नहीं दे सकते। किसी भी मामले में, यह कुछ समय के लिए प्रोग्राम के अंदर रहता है और अपने कार्यों को करता है। सटीक होने के लिए, एक वस्तु "जीवित" है जब तक कि इसके संदर्भ हैं। जैसे ही कोई संदर्भ नहीं बचा है, वस्तु "मर जाती है"। उदाहरण:


public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}

लेम्बोर्गिनी डियाब्लो कार वस्तु main()विधि की दूसरी पंक्ति पर जीवित रहना बंद कर देती है। इसका केवल एक संदर्भ था, और फिर उस संदर्भ को बराबर सेट किया गया था null। चूंकि लेम्बोर्गिनी डियाब्लो के लिए कोई शेष संदर्भ नहीं है, आवंटित स्मृति "कचरा" बन जाती है। ऐसा होने के लिए एक संदर्भ को शून्य पर सेट करने की आवश्यकता नहीं है:


public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}

यहां हमने एक दूसरा ऑब्जेक्ट बनाया और फिर इस नए ऑब्जेक्ट को lamborghiniरेफरेंस में असाइन किया। अब Lamborghini Gallardoवस्तु के दो संदर्भ हैं, लेकिन Lamborghini Diabloवस्तु के पास कोई नहीं है। इसका मतलब है कि Diabloवस्तु अब कचरा है। यह तब होता है जब जावा का अंतर्निहित तंत्र जिसे कचरा संग्राहक (जीसी) कहा जाता है, चलन में आता है।

कचरा संग्राहक एक आंतरिक जावा तंत्र है जो मेमोरी को मुक्त करने के लिए जिम्मेदार है, अर्थात मेमोरी से अनावश्यक वस्तुओं को हटाना। यहाँ एक रोबोट वैक्यूम क्लीनर की तस्वीर चुनने का एक अच्छा कारण है। आखिरकार, कचरा संग्रहकर्ता लगभग उसी तरह काम करता है: पृष्ठभूमि में, यह आपके कार्यक्रम के बारे में "यात्रा" करता है, आपकी ओर से व्यावहारिक रूप से कोई प्रयास किए बिना कचरा इकट्ठा करता है। इसका काम उन वस्तुओं को हटाना है जो अब प्रोग्राम में उपयोग नहीं की जाती हैं।

ऐसा करने से कंप्यूटर में अन्य वस्तुओं के लिए मेमोरी खाली हो जाती है। क्या आपको याद है कि पाठ की शुरुआत में हमने कहा था कि सामान्य जीवन में आपको अपने कंप्यूटर की स्थिति पर नजर रखनी होगी और अनावश्यक फाइलों को हटाना होगा? ठीक है, जावा ऑब्जेक्ट्स के मामले में, कचरा कलेक्टर आपके लिए यह करता है। जब आपका प्रोग्राम चलता है तो कचरा संग्राहक बार-बार चलता है: आपको इसे स्पष्ट रूप से कॉल करने या कमांड देने की आवश्यकता नहीं है, हालांकि यह तकनीकी रूप से संभव है। बाद में हम इसके बारे में और बात करेंगे और इसके काम का अधिक विस्तार से विश्लेषण करेंगे।

जब कचरा संग्रहकर्ता वस्तु को नष्ट करने से ठीक पहले किसी वस्तु तक पहुंचता है, तो वह finalize()वस्तु पर एक विशेष विधि - - कॉल करता है। यह विधि वस्तु द्वारा उपयोग किए जाने वाले अन्य संसाधनों को जारी कर सकती है। विधि वर्ग finalize()का हिस्सा है Objectequals()इसका मतलब है कि आपके द्वारा पहले मिले , hashCode()और विधियों के अतिरिक्त toString(), प्रत्येक वस्तु में यह विधि होती है। यह अन्य तरीकों से इस मायने में भिन्न है कि यह है - मुझे इसे कैसे कहना चाहिए - बहुत सनकी।

विशेष रूप से, किसी वस्तु के विनाश से पहले इसे हमेशा नहीं बुलाया जाता है। प्रोग्रामिंग एक सटीक प्रयास है। प्रोग्रामर कंप्यूटर को कुछ करने के लिए कहता है, और कंप्यूटर उसे करता है। मुझे लगता है कि आप पहले से ही इस व्यवहार के अभ्यस्त हैं, इसलिए सबसे पहले आपके लिए इस निम्नलिखित विचार को स्वीकार करना मुश्किल हो सकता है: "वस्तुओं के विनाश से पहले, वर्ग की विधि को कहा जाता है। finalize()या Objectशायद इसे नहीं कहा जाता है। यह सब पर निर्भर करता है। तुम्हारी किस्मत!"

फिर भी, यह सच है। जावा मशीन स्वयं यह निर्धारित करती है कि finalize()केस-दर-मामला आधार पर विधि को कॉल करना है या नहीं। उदाहरण के लिए, आइए निम्नलिखित कोड को एक प्रयोग के रूप में चलाने का प्रयास करें:


public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {
       for (int i = 0 ; i < 1000000; i++) {
           Cat cat = new Cat();
           cat = null; // This is when the first object becomes available to the garbage collector
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Cat object destroyed!");
   }
}

हम एक Catवस्तु बनाते हैं और फिर कोड की अगली पंक्ति में हम इसका एकमात्र संदर्भ शून्य के बराबर सेट करते हैं। और हम ऐसा एक लाख बार करते हैं। हम स्पष्ट रूप से finalize()विधि को ओवरराइड करते हैं ताकि यह एक स्ट्रिंग को एक लाख बार कंसोल पर प्रिंट कर सके (एक बार हर बार यह किसी Catवस्तु को नष्ट कर देता है)। लेकिन कोई नहीं! सटीक होने के लिए, यह मेरे कंप्यूटर पर केवल 37,346 बार चला! यानी, 27 बार में सिर्फ एक बार मेरी मशीन पर स्थापित जावा मशीन ने finalize()विधि को कॉल करने का निर्णय लिया।

अन्य मामलों में कचरा संग्रहण इसके बिना हुआ। इस कोड को अपने लिए चलाने का प्रयास करें: सबसे अधिक संभावना है, आपको एक अलग परिणाम मिलेगा। जैसा कि आप देख सकते हैं, finalize()शायद ही एक विश्वसनीय भागीदार कहा जा सकता है :) इसलिए, भविष्य के लिए थोड़ी सलाह: finalize()महत्वपूर्ण संसाधनों को मुक्त करने के तरीके पर भरोसा न करें। शायद जेवीएम इसे बुलाएगा, या शायद नहीं। कौन जानता है?

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

यदि प्रोग्रामर अपना कोड गलत तरीके से लिखते हैं, तो हर बार नई बनाई गई वस्तुओं के लिए नई मेमोरी आवंटित की जा सकती है, जबकि पुरानी, ​​​​अनावश्यक वस्तुएं कचरा संग्राहक द्वारा हटाने के लिए उपलब्ध नहीं हो सकती हैं। चूंकि हमने एक रोबोट वैक्यूम क्लीनर के साथ एक सादृश्य बनाया है, कल्पना करें कि क्या होगा यदि, रोबोट शुरू करने से पहले, आप घर के चारों ओर मोज़े बिखेर दें, एक कांच के फूलदान को तोड़ दें, और एक लेगो बिल्डिंग ब्लॉक्स को पूरे फर्श पर छोड़ दें। बेशक, रोबोट अपना काम करने की कोशिश करेगा, लेकिन किसी समय यह अटक जाएगा।

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

आपको इसे याद रखने की आवश्यकता नहीं है। आपको बस इसके काम करने के पीछे के सिद्धांत को समझने की जरूरत है।