java लिनक्स के तहत जावा से वर्चुअल मेमोरी उपयोग, बहुत मेमोरी का इस्तेमाल किया जाता है




मेमोरी मैनेजमेंट क्या है (7)

सन जेवीएम को हॉटस्पॉट के लिए बहुत सारी मेमोरी की आवश्यकता है और यह साझा स्मृति में रनटाइम पुस्तकालयों में मैप करता है।

अगर स्मृति एक मुद्दा है तो एम्बेड करने के लिए उपयुक्त एक और JVM का उपयोग करने पर विचार करें। आईबीएम में जे 9 है, और ओपन सोर्स "जामवम" है जो जीएनयू क्लासपाथ पुस्तकालयों का उपयोग करता है। इसके अलावा सूर्य में सनस्कॉट पर स्क्वाक जेवीएम चल रहा है, इसलिए विकल्प हैं।

मुझे लिनक्स के तहत चल रहे जावा एप्लिकेशन में कोई समस्या है।

जब मैं एप्लिकेशन को लॉन्च करता हूं, डिफ़ॉल्ट अधिकतम ढेर आकार (64 एमबी) का उपयोग करके, मैं शीर्ष एप्लिकेशन का उपयोग करके देखता हूं कि 240 एमबी वर्चुअल मेमोरी एप्लिकेशन को आवंटित की जाती है। यह कंप्यूटर पर कुछ अन्य सॉफ़्टवेयर के साथ कुछ समस्याएं उत्पन्न करता है, जो अपेक्षाकृत संसाधन-सीमित है।

जहां तक ​​मैं समझता हूं, आरक्षित वर्चुअल मेमोरी का उपयोग नहीं किया जाएगा, क्योंकि एक बार जब हम ढेर सीमा तक पहुंच जाते हैं तो OutOfMemoryError फेंक दिया जाता है। मैंने विंडोज़ के तहत एक ही एप्लीकेशन चलाया और मुझे लगता है कि वर्चुअल मेमोरी आकार और हीप आकार समान हैं।

क्या वैसे भी है कि मैं लिनक्स के तहत जावा प्रक्रिया के लिए उपयोग में वर्चुअल मेमोरी को कॉन्फ़िगर कर सकता हूं?

1 संपादित करें : समस्या ढेर नहीं है। समस्या यह है कि यदि मैं 128 एमबी का ढेर सेट करता हूं, उदाहरण के लिए, अभी भी लिनक्स 210 एमबी वर्चुअल मेमोरी आवंटित करता है, जिसकी आवश्यकता नहीं है। **

2 संपादित करें : ulimit -v का उपयोग वर्चुअल मेमोरी की मात्रा को सीमित करने की अनुमति देता है। यदि आकार सेट 204 एमबी से नीचे है, तो एप्लिकेशन नहीं चलाएगा, भले ही इसे 204 एमबी की आवश्यकता न हो, केवल 64 एमबी। इसलिए मैं समझना चाहता हूं कि जावा को इतनी वर्चुअल मेमोरी क्यों चाहिए। क्या यह बदला जा सकता है?

संपादित करें 3 : सिस्टम में चल रहे कई अन्य अनुप्रयोग हैं, जो एम्बेडेड हैं। और सिस्टम में वर्चुअल मेमोरी सीमा है (टिप्पणियों से, महत्वपूर्ण विवरण)।


जावा और glibc> = 2.10 (उबंटू> = 10.04, RHEL> = 6) के साथ एक ज्ञात समस्या है।

इलाज इस env सेट करने के लिए है। परिवर्तनीय: export MALLOC_ARENA_MAX=4 यदि आप TOMCAT_HOME/bin/setenv.sh चला रहे हैं, तो आप इसे TOMCAT_HOME/bin/setenv.sh फ़ाइल में जोड़ सकते हैं।

MALLOC_ARENA_MAX https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en सेट करने के बारे में एक आईबीएम आलेख है

यह ब्लॉग पोस्ट कहता है

निवासी स्मृति को स्मृति रिसाव या स्मृति विखंडन के समान तरीके से रेंगने के लिए जाना जाता है।

अधिक संदर्भों के लिए Google या SO पर MALLOC_ARENA_MAX की खोज करें।

आवंटित स्मृति के कम विखंडन के लिए अनुकूलित करने के लिए आप अन्य मॉलोक विकल्पों को भी ट्यून करना चाहते हैं:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

जावा प्रक्रिया के लिए आवंटित स्मृति की मात्रा काफी अपेक्षाकृत है जो मैं अपेक्षा करता हूं। मुझे एम्बेडेड / मेमोरी सीमित सिस्टम पर जावा चलाने वाली समान समस्याएं आई हैं। मनमाने ढंग से वीएम सीमाओं या उन प्रणालियों पर किसी भी एप्लिकेशन को चलाने के लिए जिनके पास पर्याप्त मात्रा में स्वैप नहीं होता है। ऐसा लगता है कि कई आधुनिक ऐप्स की प्रकृति है जो संसाधन-सीमित सिस्टम पर उपयोग के लिए डिज़ाइन नहीं हैं।

आपके पास कुछ और विकल्प हैं जिन्हें आप अपने JVM की स्मृति पदचिह्न को सीमित और सीमित कर सकते हैं। यह वर्चुअल मेमोरी पदचिह्न को कम कर सकता है:

-XX: ReservedCodeCacheSize = 32m आरक्षित कोड कैश आकार (बाइट्स में) - अधिकतम कोड कैश आकार। [सोलारिस 64-बिट, एमडी 64, और -सर x86: 48 मीटर; 1.5.0_06 और इससे पहले, सोलारिस 64-बिट और और64: 1024 मीटर।]

-XX: स्थायी पीढ़ी के MaxPermSize = 64m आकार। [5.0 और नए: 64 बिट वीएम 30% बड़े पैमाने पर बढ़ाए गए हैं; 1.4 amd64: 96 मीटर; 1.3.1 -client: 32m।]

साथ ही, आपको अपने -Xmx (अधिकतम ढेर आकार) को अपने आवेदन के वास्तविक शिखर स्मृति उपयोग के लिए यथासंभव करीब एक मान पर सेट करना चाहिए। मेरा मानना ​​है कि जेवीएम का डिफ़ॉल्ट व्यवहार अभी भी अधिकतम आकार तक विस्तारित होने पर हीप आकार को दोगुना करना है। यदि आप 32 एम ढेर से शुरू करते हैं और आपका ऐप 65 एम तक पहुंच गया है, तो ढेर 32 एम -> 64 एम -> 128 एम बढ़ रहा है।

आप ढेर को बढ़ाने के बारे में वीएम को कम आक्रामक बनाने के लिए भी कोशिश कर सकते हैं:

-XX: विस्तार से बचने के लिए जीसी के बाद MinHeapFreeRatio = 40 ढेर के न्यूनतम प्रतिशत।

इसके अलावा, कुछ साल पहले इसका प्रयोग करने से मुझे जो याद आया, उससे प्राप्त मूल पुस्तकालयों की संख्या न्यूनतम पदचिह्न पर एक बड़ा प्रभाव पड़ा। अगर मैं सही ढंग से याद करता हूं तो java.net.Socket को 15M से अधिक जोड़ा गया (और शायद मैं नहीं)।


बस एक विचार, लेकिन आप एक ulimit -v विकल्प के प्रभाव की जांच कर सकते हैं।

यह वास्तविक समाधान नहीं है क्योंकि यह सभी प्रक्रियाओं के लिए पता स्थान को सीमित कर देगा, लेकिन इससे आपको सीमित वर्चुअल मेमोरी के साथ अपने एप्लिकेशन के व्यवहार की जांच करने की अनुमति मिल जाएगी।


सूर्य के जावा 1.4 में स्मृति आकार को नियंत्रित करने के लिए निम्नलिखित तर्क हैं:

-Xmsn स्मृति आवंटन पूल के बाइट्स में प्रारंभिक आकार निर्दिष्ट करें। यह मान 1 एमबी से 1024 से अधिक का एक होना चाहिए। मेगाबाइट्स को इंगित करने के लिए किलोबाइट्स, या एम या एम को इंगित करने के लिए अक्षर के या के रूप में संलग्न करें। डिफ़ॉल्ट मान 2 एमबी है। उदाहरण:

           -Xms6291456
           -Xms6144k
           -Xms6m

-Xmxn मेमोरी आवंटन पूल के अधिकतम आकार, बाइट्स में निर्दिष्ट करें। यह मान 2 एमबी से 1024 से अधिक के एकाधिक होना चाहिए। मेगाबाइट्स को इंगित करने के लिए किलोबाइट्स, या एम या एम को इंगित करने के लिए अक्षर के या के रूप में संलग्न करें। डिफ़ॉल्ट मान 64 एमबी है। उदाहरण:

           -Xmx83886080
           -Xmx81920k
           -Xmx80m

http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html

जावा 5 और 6 में कुछ और है। http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp देखें


यह जावा के साथ एक दीर्घकालिक शिकायत रही है, लेकिन यह काफी हद तक अर्थहीन है, और आम तौर पर गलत जानकारी को देखने के आधार पर। सामान्य वाक्यांश कुछ ऐसा है जैसे "जावा पर हैलो वर्ल्ड 10 मेगाबाइट लेता है! इसकी आवश्यकता क्यों है?" खैर, नमस्ते दुनिया को 64-बिट जेवीएम दावे पर 4 गीगाबाइट्स लेने का दावा करने का एक तरीका है ... कम से कम माप के एक रूप से।

java -Xms1024m -Xmx4096m com.example.Hello

स्मृति मापने के विभिन्न तरीके

लिनक्स पर, top कमांड आपको स्मृति के लिए कई अलग-अलग संख्या देता है। हैलो वर्ल्ड उदाहरण के बारे में यह कहता है:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2120 kgregory  20   0 4373m  15m 7152 S    0  0.2   0:00.10 java
  • वीआईआरटी वर्चुअल मेमोरी स्पेस है: वर्चुअल मेमोरी मैप में सबकुछ का योग (नीचे देखें)। यह काफी हद तक व्यर्थ है, सिवाय इसके कि जब यह नहीं है (नीचे देखें)।
  • आरईएस निवासी सेट आकार है: वर्तमान में रैम में मौजूद पृष्ठों की संख्या। लगभग सभी मामलों में, यह एकमात्र संख्या है जिसका उपयोग आपको "बहुत बड़ा" कहने पर करना चाहिए। लेकिन यह अभी भी बहुत अच्छी संख्या नहीं है, खासकर जावा के बारे में बात करते समय।
  • एसएचआर निवासी स्मृति की मात्रा है जो अन्य प्रक्रियाओं के साथ साझा की जाती है। जावा प्रक्रिया के लिए, यह आम तौर पर साझा पुस्तकालयों और मेमोरी-मैप किए गए जारफाइल तक सीमित है। इस उदाहरण में, मेरे पास केवल एक जावा प्रक्रिया चल रही थी, इसलिए मुझे संदेह है कि 7k ओएस द्वारा उपयोग की जाने वाली पुस्तकालयों का परिणाम है।
  • डिफ़ॉल्ट रूप से SWAP चालू नहीं है, और यहां दिखाया नहीं गया है। यह वर्चुअल मेमोरी की मात्रा इंगित करता है जो वर्तमान में डिस्क पर निवासी है, चाहे वह वास्तव में स्वैप स्पेस में है या नहीं । ओएस रैम में सक्रिय पृष्ठों को रखने के बारे में बहुत अच्छा है, और स्वैपिंग के लिए एकमात्र इलाज (1) अधिक मेमोरी खरीदते हैं, या (2) प्रक्रियाओं की संख्या को कम करते हैं, इसलिए इस नंबर को अनदेखा करना सबसे अच्छा है।

विंडोज टास्क मैनेजर की स्थिति थोड़ा और जटिल है। विंडोज एक्सपी के तहत, "मेमोरी यूजेज" और "वर्चुअल मेमोरी साइज" कॉलम हैं, लेकिन आधिकारिक दस्तावेज उनके मतलब पर चुप है। विंडोज विस्टा और विंडोज 7 और कॉलम जोड़ते हैं, और वे वास्तव में documented । इनमें से, "कार्य सेट" माप सबसे उपयोगी है; यह लगभग लिनक्स पर आरईएस और एसएचआर के योग के अनुरूप है।

वर्चुअल मेमोरी मैप को समझना

प्रक्रिया द्वारा खपत वर्चुअल मेमोरी प्रक्रिया मेमोरी मैप में मौजूद सभी चीजों का कुल है। इसमें डेटा (उदाहरण के लिए, जावा ढेर) शामिल है, लेकिन प्रोग्राम द्वारा उपयोग की जाने वाली सभी साझा लाइब्रेरीज़ और मेमोरी-मैप की गई फ़ाइलें भी शामिल हैं। लिनक्स पर, आप प्रक्रिया स्थान में मैप की गई सभी चीजों को देखने के लिए pmap कमांड का उपयोग कर सकते हैं (यहां से बाहर मैं केवल लिनक्स का उल्लेख करने जा रहा हूं, क्योंकि मैं इसका उपयोग करता हूं; मुझे यकीन है कि इसके बराबर टूल हैं विंडोज)। "हैलो वर्ल्ड" प्रोग्राम के मेमोरी मैप से यहां एक अंश दिया गया है; संपूर्ण मेमोरी मैप 100 से अधिक लाइनों तक लंबा है, और हजारों पंक्ति सूची में असामान्य नहीं है।

0000000040000000     36K r-x--  /usr/local/java/jdk-1.6-x64/bin/java
0000000040108000      8K rwx--  /usr/local/java/jdk-1.6-x64/bin/java
0000000040eba000    676K rwx--    [ anon ]
00000006fae00000  21248K rwx--    [ anon ]
00000006fc2c0000  62720K rwx--    [ anon ]
0000000700000000 699072K rwx--    [ anon ]
000000072aab0000 2097152K rwx--    [ anon ]
00000007aaab0000 349504K rwx--    [ anon ]
00000007c0000000 1048576K rwx--    [ anon ]
...
00007fa1ed00d000   1652K r-xs-  /usr/local/java/jdk-1.6-x64/jre/lib/rt.jar
...
00007fa1ed1d3000   1024K rwx--    [ anon ]
00007fa1ed2d3000      4K -----    [ anon ]
00007fa1ed2d4000   1024K rwx--    [ anon ]
00007fa1ed3d4000      4K -----    [ anon ]
...
00007fa1f20d3000    164K r-x--  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f20fc000   1020K -----  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f21fb000     28K rwx--  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
...
00007fa1f34aa000   1576K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3634000   2044K -----  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3833000     16K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3837000      4K rwx--  /lib/x86_64-linux-gnu/libc-2.13.so
...

प्रारूप की एक त्वरित व्याख्या: प्रत्येक पंक्ति सेगमेंट के वर्चुअल मेमोरी एड्रेस के साथ शुरू होती है। इसके बाद सेगमेंट आकार, अनुमतियां, और सेगमेंट का स्रोत होता है। यह अंतिम आइटम या तो एक फ़ाइल या "एनन" है, जो mmap माध्यम से आवंटित स्मृति के ब्लॉक को इंगित करता है।

शीर्ष से शुरू, हमारे पास है

  • जेवीएम लोडर (यानी, प्रोग्राम जो java टाइप करते समय चलाया जाता है)। यह बहुत छोटा है; यह सब साझा पुस्तकालयों में लोड होता है जहां असली जेवीएम कोड संग्रहीत होता है।
  • जावा ढेर और आंतरिक डेटा रखने वाले एनन ब्लॉक का एक गुच्छा। यह एक सूर्य जेवीएम है, इसलिए ढेर कई पीढ़ियों में टूट गया है, जिनमें से प्रत्येक का अपना स्मृति ब्लॉक है। ध्यान दें कि JVM -Xmx मान के आधार पर वर्चुअल मेमोरी स्पेस आवंटित करता है; यह एक संगत ढेर होने की अनुमति देता है। -Xms मान आंतरिक रूप से यह कहने के लिए प्रयोग किया जाता है कि कार्यक्रम शुरू होने पर ढेर का "उपयोग में" कितना होता है, और कचरा संग्रह को ट्रिगर करने के लिए उस सीमा के संपर्क में आता है।
  • एक मेमोरी मैप किए गए जारफाइल, इस मामले में वह फाइल जो "जेडीके कक्षाएं" रखती है। जब आप एक जेएआर को मेमोरी-मैप करते हैं, तो आप इसके भीतर फ़ाइलों को बहुत कुशलता से एक्सेस कर सकते हैं (बनाम इसे हर बार शुरू से पढ़ते हैं)। सन जेवीएम क्लासपाथ पर सभी जेएआर को मेमोरी-मैप करेगा; यदि आपके एप्लिकेशन कोड को JAR तक पहुंचने की आवश्यकता है, तो आप इसे स्मृति-मानचित्र भी कर सकते हैं।
  • दो धागे के लिए प्रति थ्रेड डेटा। 1 एम ब्लॉक एक धागा ढेर है; मुझे नहीं पता कि 4 के ब्लॉक में क्या चल रहा है। वास्तविक ऐप के लिए, यदि आप मेमोरी मैप के माध्यम से इन सैकड़ों प्रविष्टियों को दोहराते हैं तो आपको दर्जनों दिखाई देंगे।
  • वास्तविक जेवीएम कोड रखने वाले साझा पुस्तकालयों में से एक। इनमें से कई हैं।
  • सी मानक पुस्तकालय के लिए साझा पुस्तकालय। यह केवल कई चीजों में से एक है जो JVM लोड करता है जो कि जावा का सख्ती से हिस्सा नहीं है।

साझा पुस्तकालय विशेष रूप से दिलचस्प होते हैं: प्रत्येक साझा लाइब्रेरी में कम-से-कम दो सेगमेंट होते हैं: लाइब्रेरी कोड वाला एकमात्र सेगमेंट, और एक रीड-राइट सेगमेंट जिसमें लाइब्रेरी के लिए वैश्विक प्रति-प्रक्रिया डेटा होता है (मुझे नहीं पता कि क्या बिना किसी अनुमति के सेगमेंट है; मैंने इसे केवल x64 लिनक्स पर देखा है)। लाइब्रेरी का केवल पढ़ने वाला हिस्सा लाइब्रेरी का उपयोग करने वाली सभी प्रक्रियाओं के बीच साझा किया जा सकता है; उदाहरण के लिए, libc में वर्चुअल मेमोरी स्पेस का 1.5 एम है जिसे साझा किया जा सकता है।

वर्चुअल मेमोरी आकार कब महत्वपूर्ण है?

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

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

लेकिन, यह देखते हुए कि 64-बिट मशीन सर्वव्यापी हैं, मुझे नहीं लगता कि यह वर्चुअल मेमोरी साइज पूरी तरह से अप्रासंगिक आंकड़े होने से बहुत पहले होगा।

निवासी सेट आकार कब महत्वपूर्ण है?

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

लेकिन आरएसएस भी भ्रामक है, खासकर हल्के ढंग से लोड मशीन पर। ऑपरेटिंग सिस्टम किसी प्रक्रिया द्वारा उपयोग किए जाने वाले पृष्ठों को पुनः प्राप्त करने के लिए बहुत से प्रयास नहीं करता है। ऐसा करने से हासिल करने के लिए बहुत कम लाभ होता है, और यदि भविष्य में पृष्ठ को छूता है तो महंगे पृष्ठ की गलती की संभावना है। नतीजतन, आरएसएस आंकड़े में ऐसे कई पेज शामिल हो सकते हैं जो सक्रिय उपयोग में नहीं हैं।

जमीनी स्तर

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

जावा प्रोग्राम के साथ, ढेर में क्या हो रहा है, इस पर ध्यान देना कहीं अधिक महत्वपूर्ण है। खपत की गई कुल मात्रा में महत्वपूर्ण है, और कुछ ऐसे कदम हैं जिन्हें आप कम करने के लिए ले सकते हैं। अधिक महत्वपूर्ण बात यह है कि आप कचरे के संग्रह में कितना समय व्यतीत करते हैं, और ढेर के कौन से हिस्से एकत्र किए जा रहे हैं।

डिस्क तक पहुंच (यानी, एक डेटाबेस) महंगा है, और स्मृति सस्ता है। यदि आप एक दूसरे के लिए व्यापार कर सकते हैं, तो ऐसा करें।


सीमित संसाधनों वाले सिस्टम के ढेर चूहों को कम करने का एक तरीका -XX: MaxHeapFreeRatio चर के साथ खेलना हो सकता है। यह आमतौर पर 70 पर सेट होता है, और यह जीसी को कम करने से पहले मुक्त होने वाली ढेर का अधिकतम प्रतिशत होता है। इसे कम मूल्य पर सेट करना, और आप देखेंगे कि jvisualvm प्रोफाइलर कि आमतौर पर आपके प्रोग्राम के लिए एक छोटा हीप साइस का उपयोग किया जाता है।

संपादित करें: -XX के लिए छोटे मान सेट करने के लिए: MaxHeapFreeRatio आपको भी सेट करना होगा -XX: MinHeapFreeRatio Eg

java -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=25 HelloWorld

EDIT2: एक वास्तविक एप्लिकेशन के लिए एक उदाहरण जोड़ा गया जो एक ही कार्य शुरू करता है और करता है, एक डिफ़ॉल्ट पैरामीटर के साथ और एक पैरामीटर के रूप में 10 और 25 के साथ। मैंने कोई वास्तविक गति अंतर नहीं देखा, हालांकि सिद्धांत में जावा को बाद के उदाहरण में ढेर को बढ़ाने के लिए अधिक समय का उपयोग करना चाहिए।

अंत में, अधिकतम ढेर 905 है, प्रयुक्त ढेर 378 है

अंत में, अधिकतम ढेर 722 है, प्रयुक्त ढेर 378 है

यह वास्तव में कुछ अयोग्य है, क्योंकि हमारा एप्लिकेशन दूरस्थ डेस्कटॉप सर्वर पर चलता है, और कई उपयोगकर्ता इसे एक साथ चला सकते हैं।





virtual-memory