2010-05-28 3 views
47

मुझे एक सहकर्मी के साथ विवाद सुलझाने में मदद करें: क्या कचरा संग्रह में जावा सहायता में शून्य या एक मेमोरी उपयोग को कम करने के लिए एक चर या संग्रह सेट करना है? यदि मेरे पास एक लंबा चलने वाला प्रोग्राम है और प्रत्येक फ़ंक्शन को क्रमशः बुलाया जा सकता है (संभावित रूप से हजारों बार): क्या पैरेंट फ़ंक्शन में मान लौटने से पहले सभी चरों को शून्य में सेट करना है, हेप आकार/मेमोरी उपयोग को कम करने में मदद करता है?क्या वैरिएबल = नल इसे कचरा संग्रह के लिए सेट करता है

+4

+1 अच्छा सवाल। – CoolBeans

उत्तर

57

यह पुराना प्रदर्शन है। यह 1.0 दिनों में सच था, लेकिन जरूरत को खत्म करने के लिए कंपाइलर और जेवीएम में सुधार किया गया है (यदि कभी कोई था)। यदि आप रुचि रखते हैं तो यह उत्कृष्ट आईबीएम आलेख विवरण में आता है: Java theory and practice: Garbage collection and performance

+0

+1: यह एक अच्छा लेख है और सिर्फ बारूद की तरह मैं देख रहा था। – ashurexm

+0

लिंक टूट गया था, कृपया लिंक को ठीक करें! –

+0

आलेख अभी भी http://web.archive.org पर पाया जा सकता है। देखें: http://web.archive.org/web/20130928235110/http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html –

3

आवश्यक नहीं है। ऑब्जेक्ट का संदर्भ रखने वाले अब कोई लाइव थ्रेड नहीं होने पर एक ऑब्जेक्ट कचरा संग्रह के लिए योग्य हो जाता है।

विधि चर लौटने पर स्थानीय चर के दायरे से बाहर निकलता है और स्थानीय चर को शून्य पर सेट करने के लिए कोई समझ नहीं आता है - चर किसी भी तरह गायब हो जाते हैं, और यदि कुछ और नहीं है जो संदर्भों को संदर्भित करता है, तो वे वस्तुएं कचरा संग्रह के लिए योग्य हो जाती हैं।

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

2

यह स्थानीय चर पर बेकार है, लेकिन यह आवृत्ति चर को साफ़ करने के लिए उपयोगी/आवश्यक हो सकता है जो अब आवश्यक नहीं है (उदा। पोस्ट-प्रारंभिकरण)।

(हाँ, हाँ, मुझे पता है कि बिल्डर पैटर्न लागू करने के लिए ...)

+0

यह ** ** स्थानीय varibles पर उपयोगी हो सकता है, अगर संकलक अपने स्वयं के काम नहीं कर सकता है कि varible फिर से पढ़ा नहीं जाएगा। ज्यादातर मामलों में कंपाइलर ** ** इसे स्वयं से बाहर कर सकता है। –

+0

@IanRingrose सवाल प्रक्रिया से बाहर निकलने से पहले निकलने के बारे में है। अभ्यास बेकार है। कंपाइलर कचरा-संग्रह में कोई हिस्सा नहीं निभाता है। – EJP

-4

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

+0

कुछ विशेष मामलों में यह एक अच्छा विचार हो सकता है, लेकिन आपको निश्चित रूप से हमेशा 'शून्य' पर चर सेट नहीं करना चाहिए (ध्यान दें, यह सटीक होना महत्वपूर्ण है: आप आदत से बाहर "ऑब्जेक्ट्स को नल सेट नहीं कर सकते") बिना सोच के ।इससे एक प्रकार का अंधविश्वास प्रोग्रामिंग होता है, जहां आप नहीं जानते कि आप चीजें क्यों कर रहे हैं, जो एक बुरा विचार है। – Jesper

+0

प्रश्न वापस आने से पहले निकलने के बारे में है, और यह समय बर्बाद है। – EJP

5

जावा वी एम युक्ति

12.6.1 अंतिम रूप को लागू हर वस्तु दो विशेषताओं की विशेषता जा सकता है: यह पहुंच योग्य हो सकता है, finalizer-से पहुंचा जा सकता है, या नहीं पहुंचा जा सकता है, और यह भी unfinalized हो सकता है, finalizable, या अंतिम रूप दिया गया।

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

चर्चा

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

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

यदि आप किसी फ़ील्ड या सरणी तत्व को हटा रहे हैं, तो संभवतः कुछ अनुप्रयोगों के लिए यह समझ में आ सकता है, और इससे स्मृति को फिर से पुनः प्राप्त किया जा सकता है। एक बार जब किसी वर्ग में किसी फ़ील्ड द्वारा संदर्भित मौजूदा सरणी को प्रतिस्थापित करने के लिए एक बड़ी सरणी बना रही है - यदि प्रतिस्थापन से पहले शून्य में फ़ील्ड बनाया गया है, तो यह स्मृति पर दबाव से छुटकारा पा सकता है।

जावा की एक और दिलचस्प विशेषता यह है कि स्कोप कक्षा फ़ाइलों में प्रकट नहीं होता है, इसलिए दायरा पहुंच के लिए प्रासंगिक नहीं है; इन दोनों तरीकों में एक ही बाईटकोड बनाने के लिए, और इसलिए वीएम बिल्कुल बनाई गई वस्तु के दायरे नहीं देखता:

static void withBlock() { 
    int x = 1; 

    { 
     Object a = new Object(); 
    } 

    System.out.println(x+1); 
} 

static void withoutBlock() { 
    int x = 1; 

    Object a = new Object(); 

    System.out.println(x+1); 
} 
1

यह केवल इस तरह की कुछ परिदृश्य में कुछ मतलब सकता है:

public void myHeavyMethod() { 
    List hugeList = loadHugeListOfStuff(); // lots of memory used 
    ResultX res = processHugeList(hugeList); // compute some result or summary 
    // hugeList = null; // we are done with hugeList 
    ... 
    // do a lot of other things that takes a LOT of time (seconds?) 
    // and which do not require hugeList 
    ... 
} 

यहां यह hugeList = null लाइन को असम्बद्ध करने के लिए कुछ लाभ कमा सकता है, मुझे लगता है।

लेकिन यह निश्चित रूप से विधि को फिर से लिखने के लिए अधिक समझ में आता है (शायद दो, में दोबारा प्रतिक्रिया करना या आंतरिक दायरा निर्दिष्ट करना)।

+1

केवल अगर वीएम जेवीएम स्पेक के संस्करण 3 को लागू नहीं करता है। –

+0

क्या आप विस्तारित कर सकते हैं? – leonbloy

+0

पहुंच के बारे में मेरे उत्तर में उद्धरण पढ़ें। यदि प्रक्रिया हैग्लिस्टिस्ट विशाल सूची द्वारा संदर्भित ऑब्जेक्ट का संदर्भ संग्रहीत नहीं करता है, तो इसे किसी भी लाइव थ्रेड से किसी भी संभावित निरंतर गणना में उपयोग नहीं किया जा सकता है और इसलिए पहुंच योग्य नहीं है, और इसलिए कचरा संग्रह के लिए योग्य है। यदि प्रक्रिया हूगलिस्ट केवल आकार और डेटा सरणी का उपयोग करती है (माना जाता है कि सूची एक ऐरेलिस्ट के समान है) और इन्हें रजिस्टर चर के रूप में JITted किया गया था, तो ऑब्जेक्ट को प्रक्रिया से पहले भी एकत्र किया जा सकता है। ह्यूगलिस्ट रिटर्न। –

7

लेख से:

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

अनुवाद: "स्पष्ट रूप से शून्य" लगातार वस्तुओं की आवश्यकता नहीं है। (यदि आप चाहते हैं। "वस्तुतः आवश्यक" बहुत मजबूत बयान?)

0

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

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