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


259

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

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

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

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

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

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

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


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

2
सिस्टम में कई अन्य एप्लिकेशन चल रहे हैं, जो एम्बेडेड है। और सिस्टम में वर्चुअल मेमोरी की सीमा होती है।
मारियो ऑर्टगॉन

आह्ह्ह, शैतान विवरण में है
बेजरज़रो

जावा का कौन सा कार्यान्वयन आप उपयोग कर रहे हैं। IIRC, bog standard (गैर-OpenJDK) मुक्त Sun JRE को एम्बेडेड उपयोग के लिए लाइसेंस नहीं दिया गया है।
टॉम हॉकिन -

मुझे लगता है कि मुझे "एम्बेडेड" भाग की याद आती है ... यह मेमोरी सीमित है और हार्डवेयर अनुकूलित है, लेकिन यह अभी भी एक मानक कंप्यूटर है
मारियो ऑर्टगॉन

जवाबों:


630

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

java -Xms1024m -Xmx4096m com.example.Hello

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

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

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

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

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

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

0000000040000000 36K rx--/usr/local/java/jdk-1.6-x64/bin/wava
0000000040108000 8K rwx-- /usr/local/java/jdk-1.6-x64/bin/java
0000000040eba000 676K rwx-- [anon]
00000006fae00000 21248K rwx-- [anon]
00000006fc2c0000 62720K rwx-- [एनोन]
0000000700000000 699072K rwx-- [एनोन]
000000072aab0000 2097152K rwx-- [anon]
00000007aaab0000 349504K rwx-- [एनोन]
00000007c0000000 1048576K rwx-- [आन]
...
00007fa1ed00d000 1652K r-xs- /us/local/java/jdk-1.6-x64/jre/lib/rt.jar
...
00007fa1ed1d3000 1024K rwx-- [एनोन]
00007fa1ed2d3000 4K ----- [एनोन]
00007fa1ed2d4000 1024K rwx-- [एनोन]
00007fa1ed3d4000 4K ----- [एनोन]
...
00007fa1f20d3000 164K rx--/usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f20fc000 1020K ----- /rr/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 rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3634000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3833000 16K rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3837000 4K rwx-- /lib/x86_64-linux-gnu/libc-2.13.so
...

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

ऊपर से शुरू, हमारे पास है

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

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

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

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

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

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

रेजिडेंट सेट का आकार कब महत्वपूर्ण है?

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

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

जमीनी स्तर

जब तक आप स्वैप नहीं कर रहे हैं, तब तक इस बारे में चिंतित न हों कि विभिन्न मेमोरी आंकड़े आपको क्या बता रहे हैं। इस चेतावनी के साथ कि एक निरंतर बढ़ता आरएसएस किसी तरह की स्मृति रिसाव का संकेत दे सकता है।

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

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


9
आपको ध्यान में रखना चाहिए कि मेमोरी के कुछ भाग जो वर्तमान में स्वैप किए गए हैं वे आरईएस माप से गायब हैं। तो आपके पास कम RES मान हो सकता है, लेकिन केवल इसलिए कि एप्लिकेशन निष्क्रिय था और ढेर ढेर डिस्क पर स्वैप हो गया था। जावा स्वैप करने के लिए एक बहुत बुरा काम करता है: प्रत्येक पूर्ण GC पर अधिकांश ढेर चला जाता है और कॉपी किया जाता है, यदि आपका ढेर स्वैप में था, तो GC को इसे वापस मुख्य मेमोरी में लोड करना होगा।
jrudolph

1
महान जवाब kdgregory! मैं एक सीएफ का उपयोग करके एक एम्बेडेड वातावरण में चल रहा हूं जिसमें कोई स्वैप स्थान नहीं है। तो आपके जवाब के आधार पर मेरे सभी VIRT, SWAP और nFLT मान मेमोरी मैप्ड फ़ाइलों से हैं ... जो अब कुछ समझ में आता है। क्या आप जानते हैं कि यदि SWAP मान उन पृष्ठों का प्रतिनिधित्व करते हैं जो अभी तक मेमोरी में लोड नहीं हुए हैं या उन पेजों को मेमोरी से बाहर कर दिया गया है, या दोनों हैं? हम संभावित थ्रैशिंग (तब स्वैप में निरंतर मानचित्र) का विचार कैसे प्राप्त कर सकते हैं?
पहुंचें

2
@Jeach - मुझे आश्चर्य हुआ कि किसी भी स्वैप की सूचना मिली थी, इसलिए मेरे "यात्रा लिनक्स" (उबुन्टु 10.04 और कोई स्वैप के साथ एक अंगूठे की ड्राइव) को बूट किया। जब मैंने शीर्ष में " SWAP " कॉलम को सक्षम किया , तो मैंने देखा कि ग्रहण में 509 मी था। जब मैंने इसे शामप के साथ देखा , तो कुल आभासी स्थान 650 मीटर था। इसलिए मुझे संदेह है कि "SWAP" आंकड़ा सभी ऑन-डिस्क पृष्ठों का प्रतिनिधित्व करता है, न कि केवल उन जो स्मृति में नहीं हैं।
kdgregory

2
आपके दूसरे प्रश्न के लिए: यदि आप फ्लैश कार्ड से लगातार पेज पढ़ रहे हैं, तो आपका IO प्रतीक्षा समय ( "% wa" के रूप में शीर्ष के सारांश में दिखाया गया है ) अधिक होना चाहिए। हालांकि, सावधान रहें कि यह किसी भी गतिविधि के लिए उच्च होगा, विशेष रूप से लिखता है (यह मानते हुए कि आपका कार्यक्रम कोई भी करता है)।
kdgregory

1
> 1 एम ब्लॉक एक थ्रेड स्टैक है; मुझे नहीं पता कि 4K ब्लॉक में क्या जाता है। 4K ब्लॉक - जिसे न तो पढ़ने और न ही लिखने की अनुमति के रूप में चिह्नित किया गया है - संभवतः एक गार्ड ब्लॉक है। स्टैक ओवरफ्लो पर, यह क्षेत्र एक्सेस किया जाता है, जो एक गलती को ट्रिगर करता है, जिसे JVM तब जावा StackOverflowException उत्पन्न करके संभाल सकता है। यह प्रत्येक विधि कॉल पर स्टैक पॉइंटर की जांच करने की तुलना में सस्ता है। बिना परमिशन सेट वाले गार्ड क्षेत्रों को अन्य संदर्भों में भी देखा जा सकता है।
एरिकोसे

38

Java और glibc> = 2.10 के साथ एक ज्ञात समस्या है (इसमें Ubuntu> = 10.04, RHEL> = 6 शामिल है)।

इलाज इस env को सेट करना है। चर:

export MALLOC_ARENA_MAX=4

यदि आप टॉमकैट चला रहे हैं, तो आप इसे TOMCAT_HOME/bin/setenv.shफ़ाइल में जोड़ सकते हैं ।

डॉकर के लिए, इसे डॉकरफाइल में जोड़ें

ENV MALLOC_ARENA_MAX=4

वहाँ एक आईबीएम की स्थापना के बारे 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

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

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

एक खुला JDK बग JDK-8193521 है "डिफ़ॉल्ट कॉन्फ़िगरेशन के साथ ग्लिबक कचरे की स्मृति"

अधिक संदर्भों के लिए 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

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

1
JVM देशी मेमोरी को लीक कर सकता है जो समान लक्षणों की ओर ले जाता है। Stackoverflow.com/a/35610063/166062 देखें । अस्पष्टीकृत GZIPInputStream और GZIPOutputStream उदाहरण लीक का एक स्रोत भी हो सकते हैं।
लारी होटरी

3
जावा 8 में एक JVM बग है, जिसके परिणामस्वरूप अनबाउंड देशी मेमोरी वृद्धि होती है: Bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293 - यदि यह आपको प्रभावित कर रहा है, तो MALLOC_ARENA_MAXआपकी मेमोरी की गति धीमी हो सकती है, लेकिन नहीं समस्या को पूरी तरह हल करें।
22

@ लारीहोटारी वास्तव में ग्लिबक और रेडहैट संस्करण को इंगित करने के आपके प्रयास की सराहना करते हैं
सैम

2
जावा 8u131 में संबंधित JVM बग JDK-8164293 बगs.openjdk.java.net/browse/JDK-8178124 के लिए बैकपीड बगफिक्स शामिल हैं
लारी होटरी

9

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

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

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

-XX: MaxPermSize = स्थायी पीढ़ी का 64 मीटर आकार। [५.० और नए: ६४ बिट वीएम ३०% बड़े होते हैं; 1.4 amd64: 96 मीटर; १.३.१-मूल: ३२ मी।]

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

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

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

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


7

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

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


क्या यह हॉट स्पॉट को निष्क्रिय करने का विकल्प है?
मारियो ऑर्टगॉन

शायद। आपके द्वारा उपयोग किए जाने वाले जेवीएम के लिए कमांड लाइन विकल्पों की जाँच करें।
थोर्बोजर्न रेवन एंडरसन

3

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

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


ठीक यही मेरी समस्या है। मेरा ढेर 64M पर सेट है, लेकिन लिनक्स में 204MB है। अगर मैंने 204 से नीचे का ulimit सेट किया है, तो एप्लिकेशन बिल्कुल भी नहीं चलता है।
मारियो ऑर्टगॉन 14

दिलचस्प: ulimit की स्थापना अन्य प्रक्रियाओं के लिए अनपेक्षित रूप से दुष्प्रभाव हो सकती है, यह समझाते हुए कि आवेदन क्यों नहीं चल पा रहा है।
वॉनक

समस्या यह है कि जावा को वर्चुअल मेमोरी की इस बड़ी मात्रा को आरक्षित करने की आवश्यकता है, भले ही वह इसका उपयोग नहीं करेगा। खिड़कियों में वर्चुअल मेमोरी का उपयोग किया गया है और Xmx सेटिंग अधिक निकट है।
मारियो ऑर्टगॉन

क्या आपने इसे JRockit JVM के साथ आज़माया?
वॉन

चूंकि JVM का मेमोरी आवंटन हीप आवंटन और परमिट आकार का योग है (पहले -Xms और -Xmx विकल्पों का उपयोग करके तय किया जा सकता है), क्या आपने -XX के साथ कुछ सेटिंग्स की कोशिश की थी: PermSize और -XX: MaxPermSize (JVM संस्करण के आधार पर 32MB से 64MB तक डिफ़ॉल्ट)?
वॉन

3

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

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

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

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

डिफ़ॉल्ट पैरामीटर

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

न्यूनतम 10, मैक्सहाइप 25

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

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


1

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

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

           -Xms6291456
           -Xms6144k
           -Xms6m

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

           -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 देखें


1
मेरे पास समस्या ढेर के आकार के साथ नहीं है, लेकिन लिनक्स द्वारा सौंपी गई वर्चुअल मेमोरी की मात्रा के साथ
मारियो ऑर्टगॉन

Kdgregory की व्याख्या पढ़ें। ढेर का आकार, "नया आकार", और अन्य विन्यास योग्य मापदंडों को कम करने से REAL मेमोरी की मात्रा कम हो जाएगी जो jvm लेता है।
पॉल टॉम्बलिन

उसे एक वैध समस्या हो सकती है। कुछ एप्लिकेशन (जैसे मैंने लिखा था) एक 1 जीबी फ़ाइल mmap और कुछ सिस्टम में केवल 2 जीबी की वर्चुअल मेमोरी होती है, जिनमें से कुछ साझा पुस्तकालयों से भर जाती हैं। और अगर यह समस्या है तो उसे निश्चित रूप से डीएसओ रेंडमाइजेशन को निष्क्रिय करना चाहिए। / खरीद में एक विकल्प है।
ज़ैन लिंक्स

0

नहीं, आप VM द्वारा आवश्यक मेमोरी राशि को कॉन्फ़िगर नहीं कर सकते हैं। हालांकि, ध्यान दें कि यह वर्चुअल मेमोरी है, निवासी नहीं है, इसलिए यह सिर्फ नुकसान के बिना वहां रहता है अगर वास्तव में उपयोग नहीं किया जाता है।

सचेत रूप से, आप कुछ अन्य JVM की कोशिश कर सकते हैं, फिर Sun, छोटे मेमोरी फुटप्रिंट के साथ, लेकिन मैं यहाँ सलाह नहीं दे सकता।

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