क्या जावा वस्तुओं को सेट करने से कुछ भी नहीं हो सकता है?


112

मैं कुछ पुरानी पुस्तकों को ब्राउज़ कर रहा था और पीटर हैगर द्वारा "प्रैक्टिकल जावा" की एक प्रति मिली। प्रदर्शन अनुभाग में, ऑब्जेक्ट सन्दर्भों को nullतब सेट करने की सिफारिश की जाती है जब कोई आवश्यकता नहीं होती है।

जावा में, nullप्रदर्शन या कचरा संग्रह दक्षता में सुधार करने के लिए वस्तु संदर्भ सेट करता है ? यदि हां, तो किन मामलों में यह एक मुद्दा है? कंटेनर कक्षाएं? वस्तु रचना? अनाम आंतरिक वर्ग?

मुझे यह कोड में अक्सर दिखाई देता है। क्या यह अब अप्रचलित प्रोग्रामिंग सलाह है या यह अभी भी उपयोगी है?


2
इसे प्रोफाइल करें। आधुनिक रनटाइम पर आपको प्रदर्शन या मेमोरी फ़ुटप्रिंट में कोई सार्थक वृद्धि नहीं देखनी चाहिए।
जेसन कोको

12
@ जेसन, इसे प्रोफाइल करें? यह मानता है कि मैं इसका जवाब देने के लिए एक अच्छा पर्याप्त परिणाम प्राप्त करने के लिए मामलों के एक बड़े पर्याप्त सेट को प्रोफ़ाइल करूंगा। और यह कि मैं उन मामलों का एक सेट नहीं चुनता हूं जो वीएम जीसी और प्रदर्शन के मुद्दों को पूरा करने के लिए अनुकूलित है। इसलिए मैं यहां यह पूछ रहा हूं। उन मामलों की जानकारी प्राप्त करने के लिए जहां यह एक मुद्दा है।
साल

जवाबों:


73

यह उस समय पर निर्भर करता है जब आप संदर्भ को शून्य करने की सोच रहे थे।

यदि आपके पास एक वस्तु श्रृंखला ए-> बी-> सी है, तो एक बार ए उपलब्ध नहीं है, ए, बी और सी सभी कचरा संग्रहण के लिए पात्र होंगे (यह मानते हुए कि बी या सी के अलावा कुछ भी नहीं है)। उदाहरण के लिए, A-> B या B-> C को स्पष्ट रूप से सेट करने के लिए कोई आवश्यकता नहीं है, और कभी भी कोई आवश्यकता नहीं हुई है।

इसके अलावा, ज्यादातर समय वास्तव में समस्या उत्पन्न नहीं होती है, क्योंकि वास्तव में आप संग्रह में वस्तुओं के साथ काम कर रहे हैं। आप आम तौर पर सूची, नक्शे आदि से वस्तुओं को हटाने के बारे में हमेशा सोचते रहना चाहिए, एप्रिप्ट हटाओ () विधि से।

मामला जहां अशक्त करने के लिए संदर्भों को सेट करने के लिए कुछ सलाह हुआ करती थी, विशेष रूप से एक लंबे दायरे में जहां एक मेमोरी-इंटेंसिव ऑब्जेक्ट का उपयोग गुंजाइश के माध्यम से किया जाना बंद हो गया । उदाहरण के लिए:

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

यहाँ तर्क यह था कि क्योंकि obj अभी भी स्कोप में है, तो संदर्भ के स्पष्ट शून्य के बिना , doSomethingElse () विधि के पूरा होने तक यह कचरा संग्रहणीय नहीं बनता है । और यह वह सलाह है जो शायद अब आधुनिक जेवीएम पर नहीं है : यह पता चलता है कि जेआईटी कंपाइलर उस बिंदु पर काम कर सकता है जो किसी दिए गए स्थानीय ऑब्जेक्ट संदर्भ का उपयोग नहीं करता है।


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

1
मुझे संभवतः बस जोड़ना चाहिए: ऊपर दी गई सलाह आम तौर पर पालन करने की सलाह है, अच्छी तरह से व्यवहार किए गए पुस्तकालयों, एक अच्छी तरह से व्यवहार किए गए वीएम आदि को मानते हुए। यदि आपको लगता है कि आपके पास, एक थ्रेड पूल लाइब्रेरी है, जो वस्तुओं के लिए लटका हुआ है। एक काम खत्म हो गया है, ठीक है ... उस थ्रेड पूल लाइब्रेरी में एक बग है जिसे संभवतः ऑब्जेक्ट संदर्भ को शून्य करके चारों ओर काम किया जा सकता है, लेकिन समान रूप से एक कम बग्गी थ्रेड पूल लाइब्रेरी का उपयोग करके आसपास काम किया जा सकता है। मुझे यकीन नहीं है कि इस तरह के बग सामान्य डिजाइन सिद्धांतों को बदलते हैं।
नील कॉफ़ी

25

नहीं, यह अप्रचलित सलाह नहीं है। ख़तरनाक संदर्भ अभी भी एक समस्या है, खासकर अगर आप कहते हैं, ArrayListएक पूर्व-आवंटित सरणी का उपयोग करके एक विस्तार योग्य सरणी कंटेनर ( या इस तरह) को लागू करना । सूची के "तार्किक" आकार से परे के तत्वों को समाप्त कर दिया जाना चाहिए, अन्यथा उन्हें मुक्त नहीं किया जाएगा।

प्रभावी जावा 2 एड देखें, आइटम 6: अप्रचलित वस्तु संदर्भों को हटा दें।


क्या यह भाषा का मुद्दा है या VM कार्यान्वयन का मुद्दा है?
पाब्लो सांता क्रूज़

4
यह एक "शब्दार्थ" मुद्दा है। मूल रूप से, क्योंकि आपने एक सरणी का प्रचार किया है, तो VM उसे देखता है। यह आपके कंटेनर के "तार्किक" आकार के बारे में कुछ नहीं जानता है। मान लें कि आपके पास आकार 10 का एक सरणी है, जो 16-तत्व सरणी द्वारा समर्थित है। VM यह नहीं जान सकता कि 10..15 आइटम वास्तव में उपयोग नहीं किए गए हैं; यदि उन स्लॉट्स में सामग्री है, तो उन्हें मुक्त नहीं किया जाएगा।
क्रिस जस्टर-यंग

कंटेनर कक्षाओं के बाहर क्या है? ऑब्जेक्ट कंपोज़िशन में जहां आंतरिक ऑब्जेक्ट बाहरी ऑब्जेक्ट द्वारा डी-आवंटित नहीं किया जाता है।
साल

7
@sal का सामान्य नियम यह है कि यदि आप इसे संदर्भित नहीं कर सकते हैं, तो यह कचरा एकत्र हो जाता है। इसलिए यदि बाहरी वस्तु में किसी अन्य वस्तु का संदर्भ होता है, तो यह मानते हुए कि आंतरिक वस्तु का कोई अन्य संदर्भ नहीं है, बाहरी वस्तु के एक और केवल शून्य को संदर्भित करने से संपूर्ण वस्तु को कचरा इकट्ठा हो जाएगा, जिसमें उसके अनाथ संदर्भ भी शामिल हैं।
ubermensch

2
समान आइटम 6 में आपने उल्लेख किया है: ऑब्जेक्ट संदर्भों को बाहर करना, मानक के बजाय अपवाद होना चाहिए।
एसीवी

10

इंस्टेंस फ़ील्ड, सरणी तत्व

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

पैथोलॉजिकल मामले वह वस्तु है जो पूरे XML DOM ट्री को एक असंसदीय उदाहरण देता है जो इसे कॉन्फ़िगर करने के लिए इस्तेमाल किया गया था, जो MBean अपंजीकृत नहीं था, या एक अवांछित वेब एप्लिकेशन से किसी ऑब्जेक्ट का एकल संदर्भ जो पूरे क्लासलोडर को अनलोड होने से रोकता है ।

इसलिए जब तक आप सुनिश्चित नहीं होते कि वस्तु जो स्वयं संदर्भ रखती है, वैसे भी कचरा एकत्र किया जाएगा (या फिर तब भी), आपको हर उस चीज को समाप्त कर देना चाहिए जिसकी आपको अब आवश्यकता नहीं है।

बंद चर:

यदि आप इसके दायरे के अंत से पहले एक स्थानीय चर को शून्य करने के लिए विचार कर रहे हैं, ताकि इसे कचरा कलेक्टर द्वारा पुनः प्राप्त किया जा सके और इसे "अब से अनुपयोगी" के रूप में चिह्नित किया जाए, तो आपको इसे इसके बजाय अधिक सीमित दायरे में रखने पर विचार करना चाहिए। ।

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}

हो जाता है

{
  {  
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}

कोड की सुगमता के लिए आमतौर पर लंबे, सपाट स्कोप खराब होते हैं। केवल उस उद्देश्य के लिए चीजों को तोड़ने के लिए निजी तरीकों का परिचय देना अनसुना नहीं है, भी।


यदि आप एक मजबूत संदर्भ का उल्लेख कर रहे हैं, हाँ यह सच है, लेकिन सभी संदर्भों के लिए नहीं। जावा में कमजोर संदर्भ कचरा एकत्र किया जा सकता है।
जेम्स ड्रिंकर्ड

5

मेमोरी प्रतिबंधात्मक वातावरण (जैसे सेलफोन) में यह उपयोगी हो सकता है। अशक्त होकर, objetc को gc'd होने की गुंजाइश से बाहर निकलने के लिए चर की प्रतीक्षा करने की आवश्यकता नहीं है।

हालांकि, हर रोज़ की प्रोग्रामिंग के लिए, यह नियम नहीं होना चाहिए, विशेष मामलों को छोड़कर, जैसे कि एक क्रिस जस्टर-यंग का हवाला दिया गया।


1

सबसे पहले, इसका मतलब यह नहीं है कि आप एक वस्तु सेट कर रहे हैं null। मैं इसे नीचे समझाता हूं:

List list1 = new ArrayList();
List list2 = list1;

उपरोक्त कोड सेगमेंट में हम ऑब्जेक्ट के ऑब्जेक्ट रेफरेंस वेरिएबल नाम list1को बना ArrayListरहे हैं जो मेमोरी में स्टोर होता है। तो list1उस वस्तु का जिक्र है और यह एक चर से ज्यादा कुछ नहीं है। और कोड की दूसरी पंक्ति में हम के संदर्भ कॉपी कर रहे हैं list1करने के लिए list2। तो अब मैं वापस अपने सवाल पर जा रहा हूँ:

list1 = null;

इसका मतलब list1यह है कि अब किसी भी ऑब्जेक्ट को मेमोरी में स्टोर नहीं किया जाता है, इसलिए list2रेफर करने के लिए भी कुछ नहीं होगा। तो अगर आप के आकार की जाँच करें list2:

list2.size(); //it gives you 0

तो यहाँ कचरा संग्रहकर्ता की अवधारणा आती है जो कहती है «आप को उस वस्तु को रखने वाली स्मृति को मुक्त करने के बारे में चिंता करने की कोई बात नहीं है, मैं यह करूँगा कि जब मुझे पता चलेगा कि यह अब प्रोग्राम में उपयोग नहीं किया जाएगा और JVM मुझे प्रबंधित करेगा।"

मुझे उम्मीद है कि यह अवधारणा को स्पष्ट करेगा।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.