2016-12-16 8 views
8

मेरे जावा एप्लिकेशन के लिए, मैं कमांड लाइन विकल्पों का उपयोग करके हीप मेमोरी और प्रत्यक्ष मेमोरी उपयोग को सीमित करने की कोशिश कर रहा था।जावा अनुप्रयोगों के लिए MaxDirectMemory और MaxHeapMemory सेट करना

मैं निम्नलिखित अनुप्रयोग VMware article पर आया जब मैं जावा एप्लिकेशन मेमोरी लेआउट के बारे में अधिक समझने की कोशिश कर रहा था।

लेख से, मुझे लगता है कि -एक्सएमएक्स सेटिंग का उपयोग ढेर के उपयोग को सीमित करने के लिए किया जा सकता है, जबकि मैक्सडायरेक्ट मेमरी सेटिंग का उपयोग ढेर के बाहर स्थित मूल स्मृति को सीमित करने के लिए किया जा सकता है (आरेख में अतिथि ओएस मेमोरी)। लेकिन, जब मैं एक साधारण कार्यक्रम चलाता हूं तो परिणाम अलग होते हैं। मैंने ByteBuffer.allocateDirect का उपयोग देशी स्मृति आवंटित करने के लिए किया था जबकि ByteBuffer.Hapmemory आवंटित करने के लिए आवंटित।

यह 64 बिट प्रोसेसर (ओएसएक्स) और 64 बिट जेवीएम है।

पहला प्रयोग

import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 
import java.nio.file.Paths; 
import java.nio.file.Path; 
import java.util.*; 

public class javalimits { 

    public static void main (String [] args) 
      throws Exception { 

      ArrayList al = new ArrayList(); 
      for(int i = 0; i< 100;i++) { 

        ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024* 1024); 
        al.add(bb); 
        System.out.println(" Buffer loop "+ i); 
        Thread.sleep(500); 
      } 
      Thread.sleep(10000); 
    } 
} 

जब मैं किसी भी विकल्प के बिना उपरोक्त कार्यक्रम भाग गया, यह स्मृति आवंटन की 3.6G के बाद दुर्घटनाग्रस्त हो गया। जब मैंने "-XX: MaxDirectMemorySize = 100g" विकल्प या "-Xms100g -Xmx100g" विकल्प का उपयोग किया, तो यह 65 लूप या स्मृति आवंटन के लगभग 65 ग्राम के बाद क्रैश हो गया।

मुझे समझ नहीं आता

  1. चूंकि मेरे शारीरिक राम सिर्फ 16 जी, ऐसा क्यों है स्मृति आवंटन का 16 जी के बाद दुर्घटना नहीं किया है? देशी स्मृति आवंटन के 64 जी के बारे में विशेष क्या है?
  2. "-Xms100g -Xmx100g" का उपयोग करते समय देशी स्मृति आवंटन सीमाएं कैसे बदलती हैं? मुझे लगता है कि मूल मेमोरी सीमा केवल मेरे द्वारा प्रदान किए गए लिंक में उपरोक्त आरेख के अनुसार विकल्प "" -XX: MaxDirectMemorySize = 100g "द्वारा नियंत्रित होती है। लेकिन, परिणाम अलग हैं। मेमोरी सेटिंग्स को ढेर करने से डायरेक्ट मेमोरी बफर सीमा भी बदल जाती है।
  3. क्या 3.6G स्मृति आवंटन के बारे में क्या खास बात है जब कोई आदेश पंक्ति विकल्प प्रदान की जाती हैं?

दूसरे प्रयोग

मैं देशी के बजाय ढेर स्मृति में आवंटित करने के लिए ByteBuffer.allocate को ByteBuffer.allocateDirect बदल स्मृति

import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 
import java.nio.file.Paths; 
import java.nio.file.Path; 
import java.util.*; 

public class javalimits { 

    public static void main (String [] args) 
      throws Exception { 

      ArrayList al = new ArrayList(); 
      for(int i = 0; i< 100;i++) { 

        ByteBuffer bb = ByteBuffer.allocate(1024 * 1024* 1024); 
        al.add(bb); 
        System.out.println(" Buffer loop "+ i); 
        Thread.sleep(500); 
      } 
      Thread.sleep(10000); 
    } 
} 

जब मैंने उपरोक्त प्रोग्राम को बिना किसी विकल्प के चलाया, तो यह स्मृति आवंटन के 2.7 जी के बाद दुर्घटनाग्रस्त हो गया। जब मैंने "-XX: MaxDirectMemorySize = 100g" विकल्प का उपयोग किया, तो इसका कोई प्रभाव नहीं पड़ा। यह स्मृति आवंटन के 2.7 जी के बाद दुर्घटनाग्रस्त हो गया। मुझे लगा, यह समझ में आता है। लेकिन, जब मैंने "-Xms100g -Xmx100g" विकल्प जोड़ा, तो यह 48 लूप या स्मृति आवंटन के लगभग 48 जी के बाद दुर्घटनाग्रस्त हो गया।

मुझे समझ नहीं आता क्यों,

  1. चूंकि मेरे शारीरिक राम सिर्फ 16 जी है, ऐसा क्यों है स्मृति आवंटन का 16 जी के बाद दुर्घटना नहीं किया? 48 जी ढेर मेमोरी आवंटन के बारे में विशेष क्या है?
  2. कोई कमांड लाइन विकल्प प्रदान किए जाने पर 2.7 जी मेमोरी आवंटन के बारे में विशेष क्या है?

तीसरा प्रयोग

मैं दोनों allocateDirect सक्षम है और लूप के अंदर कार्यों का आवंटन। जब मैंने "-Xms100g -Xmx100g" विकल्प जोड़ा, तो यह 24 लूप या प्रभावशाली 48 जी स्मृति आवंटन के बाद दुर्घटनाग्रस्त हो गया। (देशी स्मृति + ढेर स्मृति के 24g के 24g)

कोई मेरी मदद कर सकते समझने के लिए जहाँ मैं जावा स्मृति लेआउट समझने में गलत हूँ? (लिंक में चित्र का जिक्र करते हुए)

+0

आप अपवाद है कि फेंक दिया जाता है जब कार्यक्रम दुर्घटनाओं पोस्ट कर सकते हैं? उदाहरण के लिए अलग अपवाद अर्थ diffrernt है 'java.lang.OutOfMemoryError: प्रत्यक्ष बफर memory' से' java.lang.OutOfMemoryError अलग है: जावा ढेर space' –

+0

मैं एक अनुमान है कि इस किसी भी तरह स्मृति अदला-बदली से संबंधित है खतरे हैं। आप इसके बारे में यहां और अधिक पढ़ सकते हैं: https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html। –

+0

इसके अलावा, शायद अधिक आउटपुट प्राप्त करने के लिए ध्वज '-verbose: gc' को जोड़ने का प्रयास करें। और देखें कि क्या आप 'अपवाद' के बजाय 'थ्रोबल' पकड़ सकते हैं क्योंकि क्रैश कारण पर अधिक जानकारी हो सकती है। –

उत्तर

6

स्मृति के बारे में बहुत अच्छा स्पष्टीकरण प्रबंधन आप यहाँ पा सकते हैं: https://smarttechie.org/2016/08/15/understanding-the-java-memory-model-and-the-garbage-collection/

आपके सवालों के जवाब:

मैं क्यों समझ में नहीं आता,

  1. चूंकि मेरे शारीरिक राम सिर्फ 16 जी, ऐसा क्यों है स्मृति आवंटन का 16 जी के बाद दुर्घटना नहीं किया है? 48 जी ढेर मेमोरी आवंटन के बारे में विशेष क्या है?

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

क्या 48G के बारे में क्या खास बात है हो सकता है कि आप इस प्रणाली केवल स्मृति के इस राशि को संभालने के लिए सक्षम है। आप दलदल के साथ खेलने की कोशिश कर सकते हैं और सभी 100 जी आवंटित करने के लिए सिस्टम को अनुमति दे सकते हैं।

  1. कोई कमांड लाइन विकल्प प्रदान किए जाने पर 2.7 जी मेमोरी आवंटन के बारे में विशेष क्या है?

इससे पहले कि आप कमांड लाइन से अपने जावा चलाने इस जाँच:

विंडोज

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize" 

लिनक्स

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize' 

इसके अलावा, आप jconsol से अधिक दृश्य स्मृति आवंटन की निगरानी कर सकते हैं।

स्मृति की क्यों विभिन्न आकारों स्थित थे तो आप इस पढ़ना चाहिए:

ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()

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