2016-10-12 8 views
6

मैं एक प्रोग्राम लिखने की कोशिश कर रहा हूं जिसे एक विशिष्ट आकार की स्मृति का उपभोग करना चाहिए। एक मुद्दा जो मैं सोच रहा हूं वह यह है कि मुझे वास्तव में ढेर में एक खाली स्थान होने पर outOfMemory अपवाद मिल रहा है।पूरी मेमोरी का उपभोग नहीं कर सकता

import java.util.Vector; 
import java.lang.*; 

public class MemoryEater1 { 
    public static void main(String[] args) { 
    try { 
     long mb = Long.valueOf(args[0]); 
     Vector v = new Vector(); 
     Runtime rt = Runtime.getRuntime(); 
     while (true) { 
      if (v.size() > 0) { 
       if (((long) v.size())*100 < mb) { 
        System.out.println("total memory: " + rt.totalMemory()/1024/1024); 
        System.out.println("max memory: " + rt.maxMemory()/1024/1024); 
        System.out.println("free memory: " + rt.freeMemory()/1024/1024);       
        System.out.println("Trying to add 100 mb");     
        //100mb 
        byte b[] = new byte[104857600]; 
        v.add(b); 
       } 
      } else { 
       //100mb 
       byte b[] = new byte[104857600]; 
       v.add(b); 
       System.out.println("Added 100 mb");    
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
} 

आदेश इसे शुरू करने के:

java -Xmx4096m MemoryEater1 3000 

और उत्पादन:

total memory: 2867 
max memory: 3641 
free memory: 59 
Trying to add 100 mb 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
     at MemoryEater1.main(MemoryEater1.java:18) 

खैर अधिकतम स्मृति और कुल स्मृति के बीच अंतर है

यहाँ कोड है 774 एमबी, जो 100 एमबी अधिक उपभोग करने के लिए पर्याप्त होना चाहिए, लेकिन फिर भी त्रुटि है, और यहां तक ​​कि मशीन resourc भी है एस पर्याप्त पर्याप्त हैं:

[[email protected] ~]$ free -m 
      total  used  free  shared buffers  cached 
Mem:   15950  3447  12502   0  210  2389 
-/+ buffers/cache:  847  15102 
Swap:   4031 1759218603  8941 

ऐसा क्यों हो सकता है?

+6

क्या आपको नोट किया गया कि मुफ्त मेमोरी 100 एमबी से कम है? – Stephan

+3

जब आप बड़े सरणी आवंटित करते हैं, तो आप हमेशा जेवीएम के खतरे में भाग लेते हैं, जो आपके लिए एक विशाल संगत ब्लॉक नहीं ढूंढ पाता है, भले ही कमरे छोड़ दिया जाए। –

+2

@ स्टीफन यह केवल तभी प्रासंगिक होगा जब 'कुल स्मृति' पहले से ही 'अधिकतम स्मृति' तक विस्तारित हो। –

उत्तर

1

मुझे नहीं लगता कि यह विखंडन है क्योंकि आपके पास केवल एक थ्रेड स्मृति आवंटित है और कुछ भी पुनः प्राप्त नहीं कर रहा है।

यह आपके विशेष कचरा कलेक्टर को दोषी ठहराता है, वे स्मृति को अलग-अलग प्रबंधित करते हैं जिसके परिणामस्वरूप आपके ऐप के लिए अनुपलब्ध होता है। java -XX:+PrintCommandLineFlags के आउटपुट का विश्लेषण करके आप यह पता लगा सकते हैं कि कौन सा उपयोग किया जाता है)।

आप जी 1 का उपयोग करने की कोशिश कर सकते हैं जो स्मृति को अलग-अलग प्रबंधित करता है।

java -Xmx4096m -XX:+UseG1GC MemoryEater1 3000 

या जैसे पीढ़ी आकारों के साथ खेलते हैं -XX:NewSize और इसी तरह से।

अधिक जानकारी के लिए VM options और कचरा कलेक्टर एल्गोरिदम पर कुछ भी पढ़ें। [जीसी ट्यूनिंग]

यहां एक त्वरित उदाहरण है कि विभिन्न पीढ़ियों के लिए अलग-अलग स्मृति कैसे अनुपलब्ध हो सकती है (http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html)। Memory layout

+0

ऐसा लगता है कि उसके पास दायरे से बाहर जाने वाले बड़े एरे में से कोई भी नहीं है और इसलिए कचरा संग्रह के लिए कोई भी योग्य नहीं है। – Brick

+0

उसका कोड जीसी के हाथ से सब कुछ रखने के लिए डिज़ाइन किया गया है। – AxelH

0

आपकी मशीन पर भौतिक स्मृति से अधिक स्मृति की मात्रा के लिए जेवीएम झंडे सेट करना संभव है। अब तक दी गई जानकारी के साथ, ऐसा लगता है कि इस सरणी को आवंटित करने के लिए आपको भौतिक स्मृति की कमी है। दूसरे शब्दों में, JVM ओएस से अधिक मेमोरी का अनुरोध करता है और ओएस कहता है कि देने के लिए कोई नहीं है।

एक और संभावना यह है कि स्मृति प्रश्न विखंडन मुद्दे आपके प्रश्न पर टिप्पणियों में नोट किया गया है। मुझे लगता है कि इस मामले में आपके कार्यक्रम की संरचना के कारण कम संभावना है। मुझे नहीं लगता कि इसे बाहर मनाया जा सकता है।

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