जावा में स्टैक और हीप मेमोरी


99

जैसा कि मैं समझता हूं, जावा में, स्टैक मेमोरी प्राइमिटिव्स और विधि इनवोकेशन रखती है और हीप मेमोरी का उपयोग ऑब्जेक्ट्स को स्टोर करने के लिए किया जाता है।

मान लीजिए मेरे पास एक क्लास है

class A {
       int a ;
       String b;
       //getters and setters
}
  1. aकक्षा में आदिम कहाँ Aसंग्रहीत किया जाएगा?

  2. क्यों ढेर स्मृति मौजूद है? हम स्टैक पर सब कुछ स्टोर क्यों नहीं कर सकते?

  3. जब वस्तु को कचरा एकत्र हो जाता है, तो क्या वस्तु के साथ जुड़ा हुआ ढेर नष्ट हो जाता है?


1
stackoverflow.com/questions/1056444/is-it-on-the-stack-or-heap आपके प्रश्न का उत्तर देता है।
एस.लॉट

@ एस.लॉट, सिवाय इसके कि यह जावा के बारे में है, सी। नहीं
पेटर टॉर्क

@ पॉटर टॉर्क: सहमत। जबकि कोड नमूना जावा है, यह इंगित करने के लिए कोई टैग नहीं है कि यह केवल जावा है। और सामान्य सिद्धांत को जावा के साथ-साथ सी पर भी लागू करना चाहिए। स्टैक ओवरफ्लो पर इस सवाल के बहुत सारे उत्तर हैं।
एस.लॉट

9
@SteveHaigh: इस साइट पर, हर कोई इस बारे में बहुत चिंतित है कि क्या कुछ यहाँ है ... मुझे आश्चर्य है कि इस साइट पर क्या माइंडशेयर वास्तव में सभी सवालों के साथ मिल रहा है या नहीं।
सैम गोल्डबर्ग

जवाबों:


106

स्टैक और हीप के बीच मूल अंतर मूल्यों का जीवन चक्र है।

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

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

इसलिए यदि आप एक वस्तु बनाते हैं, तो उसे ढेर पर रख दिया जाता है, इसके साथ आने वाले सभी चर के साथ, ताकि यह फ़ंक्शन कॉल रिटर्न के बाद बनी रह सके।


2
"और केवल संदर्भ (जो बदले में आदिम हैं)" क्यों कहते हैं कि संदर्भ आदिम हैं? क्या आप कृपया स्पष्ट कर सकते हैं?
गीक

5
@ गीक: क्योंकि आदिम डेटा प्रकारों की आम परिभाषा लागू होती है: "एक प्रोग्रामिंग भाषा द्वारा बुनियादी बिल्डिंग ब्लॉक के रूप में प्रदान किया गया डेटा प्रकार" । आप यह भी देख सकते हैं कि लेख में आगे विहित उदाहरणों के बीच संदर्भ सूचीबद्ध हैं ।
बैक 2 डोस

4
@ गीक: डेटा के संदर्भ में, आप किसी भी आदिम डेटा प्रकार - संदर्भ सहित - संख्याओं के रूप में देख सकते हैं। यहां तक ​​कि charसंख्याएँ भी हैं और परस्पर भिन्न रूप से उपयोग की जा सकती हैं। सन्दर्भ भी सिर्फ एक संख्या है जो मेमोरी एड्रेस का संदर्भ देता है, या तो 32 या 64 बिट्स लंबा (हालांकि उनका उपयोग इस तरह नहीं किया जा सकता है - जब तक आप आसपास गड़बड़ नहीं करते sun.misc.Unsafe)।
सून रासमुसेन

3
इस उत्तर की शब्दावली गलत है। जावा भाषा विनिर्देश के अनुसार, संदर्भ आदिम नहीं हैं। उत्तर क्या कहता है इसका सार हालांकि सही है। (यदि आप एक तर्क यह है कि संदर्भ हैं "एक अर्थ में" कर सकते हैं जबकि आदिम द्वारा किया जाता है JLS जावा के लिए शब्दावली को परिभाषित करता है, और यह कहा गया है कि आदिम प्रकार हैं। boolean, byte, short, char, int, long, floatऔर double।)
स्टीफन सी

4
जैसा कि मैंने इस लेख में पाया , जावा स्टैक पर वस्तुओं को संग्रहीत कर सकता है (या छोटी छोटी जीवित वस्तुओं के लिए रजिस्टरों में भी)। JVM कवर के तहत काफी कुछ कर सकता है। यह कहने के लिए बिल्कुल सही नहीं है "अब जावा केवल स्टैक पर प्रिमिटिव स्टोर करता है।"

49

आदिम क्षेत्र कहाँ संग्रहीत हैं?

आदिम क्षेत्रों को उस वस्तु के हिस्से के रूप में संग्रहीत किया जाता है जो कहीं-कहीं तात्कालिक है । यह सोचने का सबसे आसान तरीका है कि यह कहाँ है - ढेर। हालांकि , यह हमेशा मामला नहीं होता है। जैसा कि जावा सिद्धांत और व्यवहार में वर्णित है : शहरी प्रदर्शन किंवदंतियों, पर दोबारा गौर :

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

इस प्रकार, यह कहने से परे कि "ऑब्जेक्ट बनाया गया है और क्षेत्र भी है", कोई यह नहीं कह सकता है कि क्या कुछ ढेर पर या स्टैक पर है। ध्यान दें कि छोटी, छोटी जीवित वस्तुओं के लिए, यह संभव है कि 'ऑब्जेक्ट' मेमोरी में मौजूद नहीं होगा और इसके बजाय इसके क्षेत्र सीधे रजिस्टरों में रखे जा सकते हैं।

कागज के साथ समाप्त होता है:

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

इस प्रकार, यदि आपके पास ऐसा कोड है जो दिखता है:

void foo(int arg) {
    Bar qux = new Bar(arg);
    ...
}

जहां उस दायरे को छोड़ने की ...अनुमति नहीं है qux, इसके बजाय स्टैक पर आवंटित किया जा qux सकता है। यह वास्तव में VM के लिए एक जीत है क्योंकि इसका मतलब है कि इसे कभी भी एकत्र किए जाने वाले कचरे की आवश्यकता नहीं है - जब यह गुंजाइश छोड़ देगा तो यह गायब हो जाएगा।

विकिपीडिया पर पलायन विश्लेषण पर अधिक । कागजों में तल्लीन करने के इच्छुक लोगों के लिए, आईबीएम से जावा के लिए एस्केप एनालिसिस । C # दुनिया से आने वालों के लिए, आप एरिक लिप्टर्ट द्वारा पढ़े गए स्टैक इज़ इंप्लीमेंटेशन डिटेल और ट्रुथ टाइप वैल्यू टाइप के बारे में जान सकते हैं (वे जावा प्रकारों के लिए भी उपयोगी हैं क्योंकि कई अवधारणाएं और पहलू समान या समान हैं) । .Net पुस्तकें स्टैक बनाम हीप मेमोरी आवंटन के बारे में बात क्यों करती हैं? इसमें भी जाता है।

ढेर के ढेर और ढेर पर

ढेर पर

तो, स्टैक या हीप क्यों है? गुंजाइश छोड़ने वाली चीजों के लिए, स्टैक महंगा हो सकता है। कोड पर विचार करें:

void foo(String arg) {
    bar(arg);
    ...
}

void bar(String arg) {
    qux(arg);
    ...
}

void qux(String arg) {
    ...
}

पैरामीटर स्टैक का भी हिस्सा हैं। इस स्थिति में कि आपके पास ढेर नहीं है, आप स्टैक पर मूल्यों का पूरा सेट पास करेंगे। यह "foo"छोटे तार के लिए ठीक है ... लेकिन अगर किसी ने उस स्ट्रिंग में एक बड़ी XML फ़ाइल डाल दी तो क्या होगा। प्रत्येक कॉल स्टैक पर पूरे विशाल स्ट्रिंग को कॉपी करेगा - और यह काफी बेकार होगा।

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

ढेर पर

आपको स्टैक की आवश्यकता नहीं है । एक, काल्पनिक रूप से, एक ऐसी भाषा लिख ​​सकता है जो स्टैक का उपयोग नहीं करता है (मनमानी गहराई का)। एक पुरानी बुनियादी बात जो मैंने अपनी युवावस्था में सीखी थी, उसने ऐसा किया था कि कोई केवल 8 स्तर की gosubकॉल कर सकता था और सभी चर वैश्विक थे - कोई स्टैक नहीं था।

स्टैक का लाभ यह है कि जब आपके पास एक वैरिएबल होता है जो एक स्कोप के साथ मौजूद होता है, जब आप उस स्कोप को छोड़ देते हैं, तो स्टैक फ्रेम पॉप हो जाता है। यह वास्तव में सरल है कि क्या है और क्या नहीं है। कार्यक्रम एक और प्रक्रिया, एक नया स्टैक फ्रेम में ले जाता है; कार्यक्रम प्रक्रिया पर लौटता है, और आप अपने वर्तमान दायरे को देखने वाले में वापस आ गए हैं; कार्यक्रम प्रक्रिया छोड़ देता है और स्टैक पर मौजूद सभी वस्तुओं को हटा दिया जाता है।

यह वास्तव में कोड को ढेर और ढेर का उपयोग करने के लिए रनटाइम लिखने वाले व्यक्ति के लिए जीवन को आसान बनाता है। वे कोड पर काम करने की कई अवधारणाओं और तरीकों से स्पष्ट रूप से सोचने वाले व्यक्ति को भाषा में कोड लिखने की अनुमति देते हैं।

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

जब कुछ कचरा इकट्ठा किया जाता है

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

मैं बताता हूं कि यह कचरा संग्रहण का एक बहुत बड़ा सरलीकरण है। कई कचरा संग्रहकर्ता हैं (यहां तक ​​कि जावा के भीतर भी - आप विभिन्न झंडे ( डॉक्स ) का उपयोग करके कचरा कलेक्टर को ट्विक कर सकते हैं । ये अलग-अलग व्यवहार करते हैं और इस बात की बारीकियां हैं कि प्रत्येक व्यक्ति इस उत्तर के लिए कितना गहरा है। आप इसे पढ़ने की इच्छा कर सकते हैं। जावा कचरा संग्रह मूल बातें इस बात का एक बेहतर विचार प्राप्त करने के लिए कि उनमें से कुछ कैसे काम करता है।

उस ने कहा, अगर कुछ स्टैक पर आवंटित किया जाता है, तो यह कचरा का हिस्सा नहीं होता है System.gc()- जब स्टैक फ्रेम का उपयोग होता है तो इसे हटा दिया जाता है। यदि कुछ ढेर पर है, और स्टैक पर कुछ से संदर्भित है, तो यह उस समय कचरा एकत्र नहीं किया जाएगा।

यह बात क्यों है?

अधिकांश भाग के लिए, इसकी परंपरा। लिखित किताबें और संकलक कक्षाएं और विभिन्न बिट्स प्रलेखन ढेर और स्टैक के बारे में एक बड़ी बात करते हैं।

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

वस्तु कहीं और है और उस स्थान पर जहां उसे सही तरीके से और जल्दी से उचित समय तक पहुंचाया जा सकता है कि वह मौजूद है। यदि इसके ढेर या ढेर पर - यह वास्तव में कोई फर्क नहीं पड़ता।


7
  1. ढेर में, ऑब्जेक्ट के हिस्से के रूप में, जिसे स्टैक में एक पॉइंटर द्वारा संदर्भित किया जाता है। अर्थात। a और b एक दूसरे के समीप जमा होंगे।
  2. क्योंकि यदि सभी मेमोरी स्टैक मेमोरी थी, तो यह किसी भी अधिक कुशल नहीं होगी। एक छोटा, तेजी से पहुंच वाला क्षेत्र होना अच्छा है जहां हम शुरू करते हैं और स्मृति के बहुत बड़े क्षेत्र में उस संदर्भ आइटम को रखते हैं। हालाँकि, यह ओवरकिल तब होता है जब कोई ऑब्जेक्ट बस एक आदिम होता है जो कि स्टैक पर लगभग उतनी ही जगह लेता है जितना कि सूचक को।
  3. हाँ।

1
मैं आपकी बात # 2 में जोड़ूंगा कि यदि आप स्टैक पर ऑब्जेक्ट संग्रहीत करते हैं (सैकड़ों प्रविष्टियों के साथ एक शब्दकोश ऑब्जेक्ट की कल्पना करें) तो इसे पास करने के लिए या इसे किसी फ़ंक्शन से वापस करने के लिए आपको ऑब्जेक्ट को कॉपी करने की आवश्यकता होगी समय। ढेर में किसी ऑब्जेक्ट के लिए एक पॉइंटर या संदर्भ का उपयोग करके, हम केवल (छोटा) संदर्भ पास करते हैं।
स्कॉट व्हिटलॉक

1
मैंने सोचा था कि 3 'नहीं' होगा क्योंकि यदि वस्तु को कचरा एकत्र किया जा रहा है, तो इसके लिए इंगित किए गए स्टैक में कोई संदर्भ नहीं है।
लूसियानो

@ लुसियानो - मैं आपकी बात देखता हूं। मैंने प्रश्न 3 को अलग ढंग से पढ़ा। "एक ही समय में" या "उस समय तक" निहित है। :: श्रग ::
पीडीआर

3
  1. ढेर पर जब तक जावा स्टैक पर क्लास के उदाहरण को एसेप्ट एनालिसिस के माध्यम से ऑप्टिमाइज़ करने के बाद आवंटित करता है कि यह शब्दार्थ को प्रभावित नहीं करेगा। यह एक कार्यान्वयन विवरण है, हालांकि, माइक्रो-ऑप्टिमाइज़ेशन को छोड़कर सभी व्यावहारिक उद्देश्यों के लिए उत्तर "ढेर पर" है।

  2. स्टैक मेमोरी को पहले आउट ऑर्डर में अंतिम रूप से आवंटित और निपटाया जाना चाहिए। हीप मेमोरी को किसी भी क्रम में आवंटित और निपटाया जा सकता है।

  3. जब ऑब्जेक्ट कचरा एकत्र किया जाता है, तो स्टैक से इसे इंगित करने वाले अधिक संदर्भ नहीं होते हैं। अगर वहाँ थे, वे वस्तु को जीवित रखेंगे। स्टैक प्राइमेटिव्स कचरा एकत्र नहीं कर रहे हैं क्योंकि वे स्वचालित रूप से नष्ट हो जाते हैं जब फ़ंक्शन वापस आता है।


3

स्टैक मेमोरी का उपयोग स्थानीय चर और फ़ंक्शन कॉल को संग्रहीत करने के लिए किया जाता है।

जबकि जावा में ऑब्जेक्ट्स को स्टोर करने के लिए हीप मेमोरी का उपयोग किया जाता है। कोई बात नहीं, जहां कोड में ऑब्जेक्ट बनाया जाता है।

कहाँ आदिम जाएगा aमें class Aसंग्रहित किया जा?

इस मामले में आदिम वर्ग ए के साथ जुड़ा हुआ है। तो यह हीप मेमोरी में बनाता है।

क्यों ढेर स्मृति मौजूद है? हम स्टैक पर सब कुछ स्टोर क्यों नहीं कर सकते?

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

जब वस्तु को कचरा एकत्र हो जाता है, तो क्या वस्तु के साथ जुड़ा हुआ ढेर नष्ट हो जाता है?

कचरा कलेक्टर हीप मेमोरी के दायरे में काम करता है, इसलिए यह उन वस्तुओं को नष्ट कर देता है जिनके पास रूट से संदर्भ श्रृंखला नहीं है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.