2011-07-14 19 views
8

मैं समझता हूं कि जब एक डायरेक्टबाइटबफर आवंटित किया जाता है, तो यह कचरा संग्रह के अधीन नहीं होता है, लेकिन मैं क्या सोच रहा हूं कि रैपिंग ऑब्जेक्ट कचरा एकत्रित है।जावा डायरेक्टबेट बफर रैपर कचरा एकत्रित हैं?

उदाहरण के लिए, यदि मैंने एक नया डायरेक्टबाइटबफर डीबीबी आवंटित किया है, और उसके बाद dbb.duplicate() का उपयोग करके डुप्लिकेट (उथला नकल) है, तो मेरे पास स्मृति के समान हिस्से के चारों ओर दो रैपर होंगे।

क्या वे रैपर कचरा संग्रह के अधीन हैं? अगर मैंने

while(true){ 
    DirectByteBuffer dbb2 = dbb.duplicate(); 
} 

क्या मैं अंत में खुद को ओम करूँगा?

+0

असल में, डायरेक्टबाइटबफर और इसकी मूल स्मृति _might_ एकत्रित कचरा हो। यह मूल आवंटित स्मृति को जारी करने के लिए एक प्रेत संदर्भ का उपयोग करता है। –

उत्तर

10

सूर्य JDK में, एक java.nio.DirectByteBufferByteBuffer#allocateDirect(int) — द्वारा बनाई प्रकार sun.misc.Cleaner, जो java.lang.ref.PhantomReference फैली का एक क्षेत्र है।

इस Cleaner (याद रखें, PhantomReference की एक उप-प्रकार) एकत्र और के बारे में जुड़े ReferenceQueue में स्थानांतरित करने के लिए है जाता है, संग्रह से संबंधित धागा नेस्टेड प्रकार ReferenceHandler के माध्यम से चल Cleaner उदाहरणों में से एक विशेष मामले के उपचार है: यह downcasts और Cleaner#clean() पर कॉल करता है, जो अंततः DirectByteBuffer$Deallocator#run() पर कॉल करने के लिए अपना रास्ता वापस बनाता है, जो बदले में Unsafe#freeMemory(long) पर कॉल करता है। वाह।

यह सर्किट है, और मैं Object#finalize() के किसी भी उपयोग को देखने में आश्चर्यचकित नहीं था। सूर्य डेवलपर्स के पास संग्रह और संदर्भ प्रबंधन उपप्रणाली के करीब भी इसे जोड़ने के कारण थे।

संक्षेप में, आप DirectByteBuffer उदाहरणों को छोड़ने वाले संदर्भों के संदर्भ में स्मृति से बाहर नहीं होंगे, जब तक कचरा कलेक्टर को त्याग पर ध्यान देने का मौका मिलेगा और इसके संदर्भ हैंडलिंग थ्रेड ऊपर वर्णित कॉल के माध्यम से प्रगति करता है।

+2

ध्यान दें कि यदि आप '-XX: + DisableExplicitGC' का उपयोग कर रहे हैं तो आपको' allocateDirect' त्रुटियों के साथ 'allOfMemory' त्रुटियों का सामना करना पड़ सकता है। आवंटन स्मृति को आरक्षित करने की कोशिश करता है और 'System.gc()' को कॉल करता है यदि यह 'फैंटॉम रिफरेंस' के पुनः दावा को ट्रिगर करने के लिए नहीं कर सकता है। –

1

DirectByteBuffer पर स्रोत कोड को देखते हुए यह सिर्फ एक नया उदाहरण देता है, इसलिए नहीं, आप स्वयं को ओम नहीं करेंगे।

जब तक आपका शेष कोड मूल dbb के संदर्भ में न हो, तब उस वस्तु को कचरा सामान्य के रूप में एकत्रित किया जाएगा। अतिरिक्त dbb2 ऑब्जेक्ट्स को कचरा इकट्ठा किया जाएगा जब उनके लिए अब कोई संदर्भ नहीं है (यानी, जबकि लूप का अंत)।

2

सीधी ByteBuffer ऑब्जेक्ट किसी अन्य ऑब्जेक्ट की तरह है: यह कचरा-एकत्रित किया जा सकता है।

एक सीधा बफर द्वारा प्रयुक्त स्मृति जारी किया जाएगा जब ByteBuffer वस्तु GC'd है (यह स्पष्ट रूप से ByteBuffer के लिए कहा गया है नहीं है, लेकिन MappedByteBuffer के प्रलेखन के अनुसार लगाए गए है)।

जहां चीजें दिलचस्प होती हैं, जब आप सीधे वर्चुअल मेमोरी स्पेस को सीधे बफर के साथ भर चुके हैं, लेकिन अभी भी ढेर में बहुत सारे कमरे हैं। यह पता चला है कि (कम से कम सूर्य जेवीएम पर), प्रत्यक्ष बफर आवंटित करते समय वर्चुअल स्पेस से बाहर चलने से जावा ढेर का जीसी ट्रिगर होगा। जो बिना संदर्भित प्रत्यक्ष बफर एकत्र कर सकता है और अपनी वर्चुअल मेमोरी प्रतिबद्धता मुक्त कर सकता है।

यदि आप 64-बिट मशीन पर चल रहे हैं, तो आपको -XX:MaxDirectMemorySize का उपयोग करना चाहिए, जो आपके द्वारा आवंटित बफर की संख्या पर ऊपरी सीमा डालता है (और जब आप उस सीमा को दबाते हैं तो जीसी भी ट्रिगर करते हैं)।

+0

डायरेक्टबाइटबफर का उपयोग कचरा संग्रहण विराम, अला टेराकोटा की बिगमेमरी के साथ कैसे किया जाता है? –

+0

@ ली पाई: क्योंकि आप एक सीधी बफर में बहुत सी धारावाहिक जावा ऑब्जेक्ट्स स्टोर कर सकते हैं। – parsifal

-2

जब एक directbytebuffer आवंटित किया जाता है, कचरा संग्रह

करने के लिए अपने अधीन नहीं तुम कहाँ है कि इस विचार से मिली? यह सही नहीं है। क्या आप उन्हें मैप्डबीटबफर के साथ मिश्रित कर रहे हैं?

+0

@downvoter क्यों? – EJP

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