2011-12-11 5 views
19

जेडीके तथाकथित प्रत्यक्ष बाइटबफर को आवंटित करने की क्षमता प्रदान करता है, जहां स्मृति को जावा ढेर के बाहर आवंटित किया जाता है। यह फायदेमंद हो सकता है क्योंकि इस स्मृति को कचरा कलेक्टर द्वारा छुआ नहीं जाता है, और इस तरह जीसी ओवरहेड में योगदान नहीं देता है: यह कैश जैसी लंबी जीवित चीजों के लिए संपत्ति के लिए बहुत उपयोगी है।देशी स्मृति की मुक्त करने के लिए मजबूर करने के उदाहरण सीधे बाइटबफर ने sun.misc.Unsafe का उपयोग करके आवंटित किया है?

हालांकि, मौजूदा कार्यान्वयन के साथ एक महत्वपूर्ण समस्या है: अंतर्निहित स्मृति केवल असीमित रूप से आवंटित की जाती है जब मालिक बाइटबफर कचरा इकट्ठा होता है; प्रारंभिक विलोपन को मजबूर करने का कोई तरीका नहीं है। यह समस्याग्रस्त हो सकता है क्योंकि जीसी चक्र स्वयं बाइटबफर को संभालने से प्रभावित नहीं है, और यह देखते हुए कि बाइटबफर पुराने ओल्ड जेनरेशन मेमोरी एरिया में रहने की संभावना है, यह संभव है कि बाइटबफर अब उपयोग में आने के कुछ घंटे बाद जीसी को बुलाया जा सके।

लेकिन सिद्धांत रूप में sun.misc.Unsafe विधियों (फ्रीमेमरी, आवंटित स्मृति) का उपयोग करना संभव होना चाहिए: जेडीके स्वयं मूल स्मृति आवंटित/हटाने के लिए उपयोग करता है। कोड को देखते हुए, मुझे लगता है कि एक संभावित चिंता स्मृति की दोहरी मुक्त होने की संभावना है - इसलिए मैं यह सुनिश्चित करना चाहता हूं कि राज्य ठीक से साफ हो जाएगा।

क्या कोई मुझे कोड पर इंगित कर सकता है जो ऐसा करता है? आदर्श रूप से जेएनए के बजाय इसका उपयोग करना चाहते हैं।

नोट: मैंने this question देखा जो संबंधित है।

ऐसा लगता है कि उत्तर देने के लिए अच्छा तरीका है: here एलिस्टिक खोज से कोड उदाहरण है जो विचार का उपयोग करता है। धन्यवाद हर कोई!

+0

यह संभव है, एसओ साल पहले पाया गया ... अब देख रहा है। (अतीत में मैंने केवल बफर के एक गोलाकार कतार का उपयोग किया, जो मेरे मामले में दबाव कम रहा।) –

+1

वाह, मुझे अभी भी कोई अच्छा लेख नहीं मिल रहा है :( –

+0

मुझे अभी तक System.gc देखना नहीं है() को कम से कम सूर्य पर नजरअंदाज किया जाना चाहिए, जो कि वैसे भी लक्ष्य है। – nilskp

उत्तर

5

sun.misc.Unsafe का उपयोग करना शायद ही संभव है क्योंकि आवंटित मूल स्मृति का मूल पता java.nio.DirectByteBuffer कन्स्ट्रक्टर का स्थानीय चर है।

वास्तव में आप निम्न कोड के साथ देशी स्मृति के मुक्त मजबूर कर सकते हैं:

import sun.misc.Cleaner; 

import java.lang.reflect.Field; 
import java.nio.ByteBuffer; 

... 

public static void main(String[] args) throws Exception { 
    ByteBuffer direct = ByteBuffer.allocateDirect(1024); 
    Field cleanerField = direct.getClass().getDeclaredField("cleaner"); 
    cleanerField.setAccessible(true); 
    Cleaner cleaner = (Cleaner) cleanerField.get(direct); 
    cleaner.clean(); 
} 
+0

ठीक है, यही कारण है कि मैंने पूछा; डीलोकेटर को कॉलबैक के साथ जोड़ा क्लीनर का पूरा ऑर्केस्ट्रेशन जटिल है। मैं इस दृष्टिकोण को आज़माउंगा, मान लीजिए कि क्लीनर पहुंच योग्य है (मैंने देखा कि जिस चीज पर यह कॉल है वह नहीं है)। – StaxMan

2

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

+0

हां, बहुत उच्च स्तर पर - लेकिन क्या आपने वास्तव में विवरणों को देखा है? यही वह जगह है जहां समस्या शुरू होती है: ऐसा करने के लिए कोई तरीका नहीं है (प्रत्यक्ष) बाइटबफर, कोई करीबी() विधि नहीं। और यहां तक ​​कि हुड के नीचे, चीजें जटिल हैं, दुर्भाग्य से। – StaxMan

+0

हां लेकिन आप असुरक्षित का उपयोग करके अपने स्वयं के बफर को लागू करके गेम को बदल सकते हैं। (जो शायद झूठी साझाकरण से बचने के लिए गद्देदार स्मृति के साथ बहुत अच्छा काम करता है, लेकिन यह एक अलग अलग गेंद गेम है) –

+0

पर्याप्त है। और मेरे मामले में, मैं पूरी तरह से सभी पहुंच को नियंत्रित करता हूं, इसलिए अंतर्निहित कच्चे भंडारण को न तो खुलासा किया जाता है और न ही संदर्भों को लटकने का खतरा होना चाहिए। – StaxMan

25

स्मृति साफ करने के लिए एक बहुत सरल तरीका है।

public static void clean(ByteBuffer bb) { 
    if(bb == null) return; 
    Cleaner cleaner = ((DirectBuffer) bb).cleaner(); 
    if (cleaner != null) cleaner.clean(); 
} 

यदि आप प्रत्यक्ष या स्मृति मैप किए गए बाइटबफर को काफी तेज़ी से हटा रहे हैं तो इसका उपयोग करना एक बड़ा अंतर हो सकता है।

ऐसा करने के लिए क्लीनर का उपयोग करने के कारणों में से एक यह है कि आप अंतर्निहित स्मृति संसाधनों की कई प्रतियां प्राप्त कर सकते हैं उदा। टुकड़ा() के साथ। और क्लीनर की संसाधन संख्या है।

+1

हम्म। मैं क्लीनर को देख रहा था, लेकिन यह सुनिश्चित नहीं था कि एक्सेस अधिकार मुझे सीधे कॉल करने देगी ... लेकिन यदि ऐसा है, तो यह निश्चित रूप से जाने का एक अच्छा तरीका होगा। धन्यवाद - शायद मैं इस दृष्टिकोण को छोड़ने में बहुत जल्दबाजी कर रहा था! – StaxMan

+0

मैंने इस परियोजना का उपयोग कई परियोजनाओं में किया है। प्रतिबिंब IMHO का उपयोग करने से बेहतर है। –

+0

सही - जब तक कक्षाएं सुलभ हों, मैं सहमत हूं। असुरक्षित खुद के संभावित मामले का समर्थन करने की आवश्यकता होने पर कोड को स्वचालित रूप से लोड किया जा सकता है। एक बार फिर धन्यवाद! – StaxMan

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