2010-01-19 14 views
8

मैंने सुना है कि जावा की सबसे खूबसूरत संपत्ति कचरा संग्रह है, मुझे पता है कि यह गारंटी देता है कि कोई प्रोग्राम स्मृति से बाहर नहीं होगा?क्या कचरा संग्रह गारंटी देता है कि कोई प्रोग्राम स्मृति से बाहर नहीं होगा?

+4

कचरा संग्रहण का मतलब है कि मेरी बहु-टेराबाइट एप्लिकेशन कभी नहीं स्मृति समाप्त हो गई है, तो उस बड़े डेटासेट के प्रसंस्करण के लिए सचमुच कमाल किया जाएगा। –

उत्तर

10

नहीं, यह इसकी गारंटी नहीं देता है। एक प्रोग्रामर के लिए गलती से ऐसी वस्तुओं को बनाने के लिए यह संभव है जो कभी भी गुंजाइश से बाहर न जाए, इस प्रकार सभी ढेर समाप्त होने तक अधिक से अधिक स्मृति का उपभोग हो जाता है।

यह सुनिश्चित करने के लिए प्रोग्रामर की ज़िम्मेदारी है कि ऑब्जेक्ट्स अब उपयोग में नहीं हैं अब द्वारा संदर्भित नहीं हैं। इस तरह कचरा कलेक्टर अपनी नौकरी कर सकता है और इन वस्तुओं द्वारा उपयोग की जाने वाली स्मृति को पुनः प्राप्त कर सकता है।

उदाहरण

public class Main { 
    public static void main(String[] main) { 
    List<String> l = new LinkedList<String>(); 

    // Enter infinite loop which will add a String to 
    // the list: l on each iteration. 
    do { 
     l.add(new String("Hello, World")); 
    } while(true); 
    } 
} 
+0

यदि आप स्ट्रिंग को बड़ा बनाते हैं तो आप मेमोरी को बहुत तेजी से खून कर सकते थे :) – medopal

+0

दरअसल ... हालांकि मैंने स्पष्ट स्ट्रिंग को संदर्भित करने से बचने के लिए स्पष्ट रूप से "नया" कहा है। – Adamski

2

नहीं। आप वस्तुओं (लाखों) का एक बहुत का निर्माण और उन्हें एक ArrayList को जोड़कर उन्हें के लिए एक संदर्भ रखना ताकि वे उदाहरण के लिए गुंजाइश (से बाहर जाना नहीं है, तो), आप एड्रेसेबल मेमोरी से बाहर हो सकते हैं।

4

नहीं, स्मृति से बाहर निकलने के कई तरीके अभी भी हैं। कचरा कलेक्टर केवल उन वस्तुओं के लिए स्मृति को पुनः प्राप्त कर सकता है जिन्हें अब संदर्भित नहीं किया जाता है - यह सुनिश्चित करने के लिए आप पर निर्भर है कि आप उन वस्तुओं का संदर्भ नहीं दे रहे हैं जिनकी आपको आवश्यकता नहीं है, या उन वस्तुओं के लिए सॉफ्ट संदर्भों का उपयोग करने के लिए जो आप चाहते हैं, लेकिन डॉन अगर स्मृति तंग हो जाती है तो दिमाग गायब नहीं होता है।

22

नहीं, यह हमेशा संभव है कि आप उपलब्ध होने से अधिक स्मृति आवंटित करने का प्रयास करेंगे।

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

1

बिलकुल नहीं। यहां तक ​​कि जावा जैसे एकत्रित कचरे में भी आप संदर्भों को आसानी से खो सकते हैं, जिसका अर्थ है कि वस्तुओं को कभी कचरा नहीं मिलेगा।

तब भी, आप सिस्टम को संभालने के लिए बहुत सारी ऑब्जेक्ट्स को तत्काल (और संदर्भित) कर सकते हैं।

1

कुछ भी सुनिश्चित करें कि कोई प्रोग्राम नए आवंटन के लिए जगह बनाने के लिए स्मृति से आइटम को मनमाने ढंग से हटाने की स्मृति से बाहर नहीं चलाता है?

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

0

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

0

नहीं, बिलकुल नहीं।

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

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

उदाहरण के लिए, यदि आपके सिस्टम में 1000 ब्लॉक उपलब्ध हैं और आपको एक ही समय में 1500 की आवश्यकता है, तो दुनिया में कोई भी जीसी आपकी मदद करने जा रही है क्योंकि रीसाइक्लिंग के लिए वास्तव में कुछ भी उपलब्ध नहीं है।

0

नहीं, कचरा संग्रह गारंटी नहीं दे सकता कि आपका एप्लिकेशन स्मृति से बाहर नहीं होगा। यह गारंटी भी नहीं देगा कि स्मृति उपलब्ध होने पर आपका एप्लिकेशन स्मृति से बाहर नहीं होगा। यदि आप मेमोरी से बाहर निकलने के करीब आते हैं या कई ऑब्जेक्ट आवंटित कर रहे हैं तो यह जीसी को थ्रैश कर सकता है, जिससे मेमोरी अपवाद से बाहर निकलता है। कार्यक्रम स्मृति से बाहर भी हो सकता है जब उसने सभी भौतिक स्मृति (वास्तविक और आभासी) का उपयोग किया है या प्रोग्राम JVM (see -Xmx) द्वारा अनुमत अधिकतम मेमोरी से अधिक है।

0

नहीं कचरा कलेक्टर, आपको अप्रयुक्त स्मृति को स्वचालित रूप से मुक्त करने में मदद करता है।

जिस तरह से यह काम करता है, यदि किसी ऑब्जेक्ट संदर्भ तक नहीं पहुंचा जा सकता है, तो उस ऑब्जेक्ट की स्मृति कचरा एकत्र हो सकती है।

उदाहरण के लिए:

public void test() { 
    Object o = new Object(); 
    // the memory used by o may be garbage collected after this line 
} 

लेकिन अगर आप कभी नहीं वस्तु संदर्भ जारी, कचरा कलेक्टर कुछ भी इकट्ठा कभी नहीं होगा और एक OutOfMemoryError फेंक दिया जाएगा।

List list = .... 
public void test() { 
    o = new Object(); 
    list.add(o); 
    // the memory used by o WON'T be garbage collected after this line 
    // because its reference is used in the list. 
} 

आप इस कई बार उपयोग करते हैं:

while(true) { 
    test(); 
} 

सूची जब तक आप स्मृति

से बाहर
3

चलाने अपने प्रश्न, NO उत्तर देने के लिए अनिश्चित काल के लिए बढ़ रहा रखेंगे। कचरा संग्रह गारंटी नहीं देता है कि एक प्रोग्राम स्मृति से बाहर नहीं होगा।

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

unreferenced वस्तुओं कचरा कचरा कलेक्टर द्वारा स्वचालित रूप से एकत्र किया जाएगा। जावा में, विधि से बाहर आने के बाद ऑब्जेक्ट्स के अधिकांश संदर्भ स्वचालित रूप से रिलीज़ हो जाते हैं।

ऑब्जेक्ट्स में अन्य ऑब्जेक्ट्स का संदर्भ है, जो बदले में अन्य ऑब्जेक्ट्स को पूरे ऑब्जेक्ट ग्राफ़ बनाने के लिए संदर्भित करता है। इसलिए इस तरह के ऑब्जेक्ट को एक से अधिक ऑब्जेक्ट द्वारा संदर्भित किया जा सकता है।

  • वस्तु शून्य संदर्भ रही है, तो यह कचरा संग्रह के लिए पात्र है।
  • वस्तुओं को ढेर पर आवंटित किया जाता है।
  • कचरा कलेक्टर समय से -समय पर रन ढेर से unreferenced वस्तुओं को हटाने के लिए ।
  • आप को रिहा बिना ढेर पर अधिक वस्तुओं बनाने करते रहे तो आप अंततः OutOfMemoryError

उदाहरण कचरा संग्रहण के साथ काम

public class TestGarbageNoError { 

public static void main(String[] args) { 
    String hugeString; 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    hugeString = getHugeString(); 
    // At each iteration reference variable hugeString 
    // points to new String object. Hence there will be 
    // zero reference to previous string object and will 
    // eventually be garbage collected 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 

पर मिल जाएगा।

काम पर स्मृति रिसाव के साथ उदाहरण

public class TestGarbageError { 

public static void main(String[] args) { 
    Collection<String> memoryLeak = new ArrayList<String>(); 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    String hugeString = getHugeString(); 
    memoryLeak.add(hugeString); 
    // At each iteration reference variable hugeString 
    // points to new String object. But all objects are added 
    // to memoryLeak Collection and will always have atleast one 
    // reference, i.e. from memoryLeak object. Hence this string 
    // objects will never be garbage collected and program will 
    // eventually run out of memory 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 
+0

इसे समझ में नहीं आ रहा है, दूसरे उदाहरण में स्ट्रिंग को लूप के लिए परिभाषित किया गया है, इसलिए प्रत्येक पुनरावृत्ति सूचक स्टैक पर खो जा रहा है, शायद नए के साथ ओवरराइट किया गया है (यह देखने का मेरा तरीका है कि चीजें कैसे चल रही हैं)। कृपया बताएं कि इस स्ट्रिंग ऑब्जेक्ट के साथ प्रत्येक पुनरावृत्ति पर क्या होता है .... –

+0

आपने "memoryLeak.add (hugeString)" पंक्ति को याद किया है। यह वह जगह है जहां प्रत्येक स्ट्रिंग का संदर्भ बनाए रखा जाता है जिसके कारण स्मृति को लीक किया जाता है। दोनों कार्यक्रमों को चलाने का प्रयास करें, आप परिणामों में अंतर देखेंगे। –

+0

आह ... हाँ, अब मैंने उस अतिरिक्त रेखा को देखा है। ऑफकोर्स, अगर कहीं कोड मेमोरी है Leak.get (..), objetc स्ट्रिंग के संदर्भ में होना है। मैंने सोचा था कि कुछ परिभाषा के स्थान पर था जहां स्ट्रिंग विशाल स्ट्रिंग रखा गया है ... –

0

हालांकि, यह गारंटी है कि इससे पहले कि JVM वाणी OutOfMemoryException यह कचरा सभी संग्रहणीय संदर्भ इकट्ठा करने और अब मुक्त स्मृति का उपयोग करने पर विचार करेगी।

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