java - जावा में मेमोरी रिसाव का सबसे आसान तरीका?




memory-leaks (6)

  1. कक्षा के दायरे में वस्तुओं का एक संग्रह बनाएं
  2. समय-समय पर संग्रह करने के लिए नई ऑब्जेक्ट्स जोड़ें
  3. संग्रह को धारण करने वाले वर्ग के उदाहरण के संदर्भ को मत छोड़ें

चूंकि कलेक्शन के मालिक के पास ऑब्जेक्ट का संग्रह और उदाहरण है, कचरा कलेक्टर हमेशा उस स्मृति को कभी भी साफ नहीं करेगा, जिससे इस प्रकार समय के साथ "रिसाव" पैदा हो।

संभव डुप्लिकेट:
जावा के साथ स्मृति रिसाव बनाना

जावा मेमोरी रिसाव का सबसे आसान तरीका क्या है?


"कंप्यूटर साइंस (या रिसाव, इस संदर्भ में) में स्मृति रिसाव होता है, तब तब होता है जब एक कंप्यूटर प्रोग्राम स्मृति का उपयोग करता है, लेकिन इसे ऑपरेटिंग सिस्टम पर वापस नहीं लाया जा सकता है।" (विकिपीडिया)

आसान जवाब है: आप नहीं कर सकते जावा स्वत: स्मृति प्रबंधन करता है और संसाधनों को मुक्त करेगा जो आपके लिए आवश्यक नहीं हैं। आप ऐसा होने से रोक नहीं सकते यह हमेशा संसाधनों को जारी करने में सक्षम होगा। मैनुअल मेमोरी प्रबंधन के साथ कार्यक्रम में, यह अलग है। आप कुछ स्मृति को सी में malloc () का उपयोग कर सकते हैं स्मृति को मुक्त करने के लिए, आपको संकेतक की आवश्यकता होती है कि malloc वापस आ गया है और उस पर निःशुल्क कॉल करें () लेकिन अगर आपके पास अब और संकेतक नहीं है (ओवरराइट या आजीवन पार हो गया), तो आप दुर्भाग्य से इस स्मृति को मुक्त करने में असमर्थ हैं और इस प्रकार आपके पास स्मृति रिसाव है।

अन्य सभी उत्तर अब तक मेरी परिभाषा में नहीं हैं, वास्तव में मेमोरी लीक। वे सभी को निरर्थक चीजों के साथ स्मृति को भरने के उद्देश्य से तेजी से तेज़ हैं लेकिन किसी भी समय आप अब भी वस्तुओं को डीरेफर करने के लिए तैयार कर सकते हैं और इस तरह स्मृति को मुक्त कर सकते हैं - कोई भी लीक नहीं। एसीसीन्रद का जवाब बहुत करीब आता है, हालांकि मुझे अपना समाधान प्रभावी होने के बाद से स्वीकार करना पड़ता है, क्योंकि यह कचरा कलेक्टर को "अंतहीन लूप" में मजबूर करके "क्रैश" करता है)।

लंबे उत्तर यह है: आप जेएनआई का उपयोग करते हुए जावा के लिए एक पुस्तकालय लिखकर मेमोरी रिसाव प्राप्त कर सकते हैं, जिसमें मैन्युअल मेमोरी प्रबंधन हो सकता है और इस प्रकार मेमोरी लीक हो सकता है। यदि आप इस लाइब्रेरी को कॉल करते हैं, तो आपकी जावा प्रक्रिया स्मृति को लीक करेगी। या, आप जेवीएम में बग बना सकते हैं, जिससे कि जेवीएम स्मृति को खो देता है संभवत: जेवीएम में कीड़े हैं, वहां कुछ ज्ञात भी हो सकते हैं क्योंकि कचरा संग्रहण वह तुच्छ नहीं है, लेकिन फिर भी यह एक बग है। डिजाइन से यह संभव नहीं है। आप कुछ जावा कोड के लिए पूछ सकते हैं जो इस तरह के बग से प्रभावित होता है माफ करना, मुझे एक नहीं पता है और यह अगले जावा संस्करण में अब भी एक बग नहीं हो सकता है।


इस सरल वर्ग को आज़माएं:

public class Memory {
private Map<String, List<Object>> dontGarbageMe = new HashMap<String, List<Object>>();

public Memory() {
    dontGarbageMe.put("map", new ArrayList<Object>());
}

public void useMemInMB(long size) {
    System.out.println("Before=" + getFreeMemInMB() + " MB");

    long before = getFreeMemInMB();
    while ((before  - getFreeMemInMB()) < size) { 
        dontGarbageMe.get("map").add("aaaaaaaaaaaaaaaaaaaaaa");
    }

    dontGarbageMe.put("map", null);

    System.out.println("After=" + getFreeMemInMB() + " MB");
}

private long getFreeMemInMB() {
    return Runtime.getRuntime().freeMemory() / (1024 * 1024);
}

public static void main(String[] args) {
    Memory m = new Memory();
    m.useMemInMB(15);  // put here apropriate huge value
}
}

ऐसा लगता है कि अधिकांश उत्तर सी शैली मेमोरी लीक नहीं हैं I

मैंने सोचा था कि मैं एक बग के साथ एक लाइब्रेरी क्लास का एक उदाहरण जोड़ूंगा जो आपको मेमोरी अपवाद के बाहर देगा दोबारा, यह एक सच मेमोरी रिसाव नहीं है, लेकिन ऐसी स्मृति का एक उदाहरण है जिसे आप उम्मीद नहीं करेंगे।

public class Scratch {
    public static void main(String[] args) throws Exception {
        long lastOut = System.currentTimeMillis();
        File file = new File("deleteme.txt");

        ObjectOutputStream out;
        try {
            out = new ObjectOutputStream(
                    new FileOutputStream("deleteme.txt"));

            while (true) {
                out.writeUnshared(new LittleObject());
                if ((System.currentTimeMillis() - lastOut) > 2000) {
                    lastOut = System.currentTimeMillis();
                    System.out.println("Size " + file.length());
                    // out.reset();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class LittleObject implements Serializable {
    int x = 0;
}

आपको मूल कोड और बग का विवरण मिल जाएगा

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4363937


यहाँ एक सरल उदाहरण है

public class finalizer {
    @Override
        protected void finalize() throws Throwable {
        while (true) {
            Thread.yield();
        }
    }

    public static void main(String[] args) {
        while (true) {
            for (int i = 0; i < 100000; i++) {
                finalizer f = new finalizer();
            }

            System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
        }
    }
}

public static List<byte[]> list = new ArrayList<byte[]>();

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

जावा में, यदि आप किसी ऑब्जेक्ट को डीरेफर कर रहे हैं (यह दायरे से बाहर है), तो यह कचरा-एकत्र है। इसलिए आपको स्मृति समस्या होने के लिए इसके संदर्भ को पकड़ना होगा।





memory-leaks