2010-01-18 13 views
12

जावा वेब ऐप में प्रदर्शन के संबंध में एक छोटा सा सवाल।जावा संग्रह और कचरा कलेक्टर

मान लीजिए कि मेरे पास List<Rubrique>listRubriques है जिसमेंऑब्जेक्ट्स हैं।

एक Rubrique (List<product>listProducts) उत्पादों में से एक सूची और ग्राहकों में से एक सूची (List<Client>listClients) शामिल हैं।

वास्तव में क्या स्मृति में होता है अगर मैं यह कर:

listRubriques.clear(); listRubriques = null; 

देखने की मेरी बात यह है कि हो सकता है, के बाद से listRubriques खाली है, मेरे सभी वस्तुओं (listProducts और listClients सहित) पहले से इस सूची से संदर्भित किया जाएगा कचरा बहुत जल्द इकट्ठा किया। लेकिन जावा में संग्रह के बाद से एक छोटा सा मुश्किल कर रहे हैं और जब से मैं अपने ऐप मैं सवाल :)

संपादित पूछ रहा हूँ के साथ काफी प्रदर्शन के मुद्दों है: चलो अब लगता है कि मेरी ग्राहक वस्तु एक List<Client> शामिल हैं। इसलिए, मेरे पास मेरी वस्तुओं के बीच एक गोलाकार संदर्भ है। तब क्या होगा यदि मेरा listRubriquenull पर सेट हो गया है? इस बार, मेरा दृष्टिकोण यह होगा कि मेरी ग्राहक वस्तुएं "पहुंचने योग्य" बन जाएंगी और मेमोरी रिसाव बना सकती है?

उत्तर

14

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

ने कहा कि आपके उदाहरण वास्तव में प्रदर्शन को नुकसान पहुंचाते हैं। listRubriques.clear() अनियंत्रित है (सिवाय इसके कि आप इसे किसी और संदर्भ में रखते हैं), क्योंकि सूची द्वारा संदर्भित सब कुछ Rubrique पल सूची कचरा है अब Rubriques संदर्भित नहीं है। listRubriques = null भी अनियंत्रित हो सकता है यदि परिवर्तनीय सूची Rubriques बाद में दायरे से बाहर हो जाती है (संभवतः क्योंकि यह एक स्थानीय चर है और विधि यहां समाप्त होती है)।

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

This article जावा कचरा कलेक्टर के बारे में अधिक जानकारी प्राप्त करने के लिए एक अच्छा संदर्भ है।

संपादित: प्रश्न में संपादित करें पर प्रतिक्रिया करने के लिए: कचरा कलेक्टर (सूर्य द्वारा प्रयोग किया जाता कार्यान्वयन कम से कम) कुछ जड़ संदर्भ और प्रतियां सभी वस्तुओं यह इस संदर्भ से पहुंच सकते हैं और है कि कर सकते हैं द्वारा संदर्भित कर रहे हैं से शुरू कर रहा है कॉपी की गई वस्तुओं। तो आपके परिपत्र संदर्भित वस्तुएं कचरा हैं, क्योंकि 'बाहरी' संदर्भ उन्हें इंगित नहीं कर रहा है और स्मृति को कचरा संग्रह में पुनः दावा किया जाएगा।

+0

सावधान: आपका पहला वाक्य सूर्य जेवीएम के वर्तमान कार्यान्वयन का वर्णन करता है। यह एक बयान नहीं है जो आम तौर पर जावा के बारे में सच है। बाकी का जवाब आम तौर पर लागू होता प्रतीत होता है, 'हालांकि। –

+0

संकेत के लिए धन्यवाद, मैंने पहली वाक्य बदल दी। – Mnementh

3

यदि आपके पास:

listRubriques = null; 

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

System.gc(); 

JVM आपको लगता है कि इस समय कचरा संग्रहण चल रहा एक अच्छा विचार है करने के लिए सिफारिश करने के लिए। लेकिन फिर भी, कोई गारंटी नहीं है।

इसके अलावा

listRubriques.clear(); 

होने null को listRubriques सेट करने से पहले आवश्यक नहीं है।

संपादित: वृत्तीय संदर्भ के बारे में आपके प्रश्न का उत्तर करने के लिए, JVMs बहुत चालाक यह पता लगाने की है कि पूरे वस्तु ग्राफ किसी भी सक्रिय रूप से चल रहा है कोड से काट दिया जाता है और JVM सही ढंग से तय करेंगे कि वे सभी कचरा संग्रहण के लिए पात्र हैं कर रहे हैं। संदर्भ गणना के बुरे पुराने दिनों में भी यह हमेशा सच रहा है। आधुनिक जेवीएम बस तेज और अधिक कुशल हैं। लेकिन वे पुरानी जेवीएम की तुलना में किसी और वस्तु को इकट्ठा करने वाले कचरे नहीं हैं।

+0

शून्य से पहले स्पष्ट के बारे में मैंने यह सुनिश्चित करने के लिए किया कि मेरे ऑब्जेक्ट में अब कोई संदर्भ नहीं होगा। लेकिन मैं ठीक हूँ यह एक बेकार डबल चेक है। मैंने पढ़ा कि System.gc(); पुराने जावा संस्करणों में उपयोगी था लेकिन आजकल पूरी तरह अनदेखा है, है ना? – Anth0

+0

@ एन्थ 0: मैंने यह नहीं सुना है और जावा 6 के लिए जे 2 एसई दस्तावेज़ों में ऐसा कुछ भी नहीं है (http://java.sun.com/javase/6/docs/api/java/lang/System.html # जीसी())। अधिकतम पोर्टेबिलिटी के लिए, यह सर्वोत्तम है कि आपके एप पर चल रहे जेवीएम कार्यान्वयन के बारे में कोई धारणा न हो। कचरा संग्रह के बारे में सच्चाई के लिए सूर्य से इस आलेख को देखें: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html – Asaph

+0

System.gc() को आमंत्रित करना आमतौर पर नए द्वारा प्रदान किया जाता है वीएम भी, हालांकि गारंटी नहीं है। यदि आप जीसी चलाने के लिए अनुरोध करते हैं, हालांकि यह आवश्यक नहीं है, हालांकि आप संभावित रूप से प्रदर्शन समस्या बना रहे हैं और एक को हल नहीं कर रहे हैं। – jarnbjo

1

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

एकमात्र ऐसी स्थिति जहां वीएम विनिर्देश गारंटी देता है कि जीसी चलाएगा, जब किसी बिंदु पर अन्यथा आउटऑफमेमरी एरर फेंक दिया जाएगा। OutOfMemoryError फेंकने से पहले, वीएम को कम से कम योग्य ऑब्जेक्ट उदाहरणों को कम से कम इकट्ठा करने का प्रयास करने के लिए बाध्य किया जाता है, कि प्रासंगिक स्मृति आवंटन अनुरोध सफल हो सकता है (लेकिन आप अभी भी गारंटी नहीं दे रहे हैं कि सभी योग्य उदाहरण एकत्र किए गए हैं)।

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