2013-03-05 4 views
11

मान लीजिए मैं निम्नलिखित कोड है:जावा कूड़ा संग्रह

public void process() { 
    byte[] data = new byte[size]; 
    ... // code that uses the above data 
    longProcess(); // a very long running process that does not use the data. 
} 

यह मानते हुए कि डेटा कार्यक्रम में कहीं और संदर्भित नहीं है, पर्याप्त JVM स्मार्ट डेटा कचरा होने के लिए अनुमति देने के लिए है एकत्रित होने पर लंबी प्रक्रिया अभी भी चल रही है?

यदि नहीं, तो

data = null; 

जोड़ने जाएगा लंबी प्रक्रिया से पहले ऐसा करने की अनुमति?

+0

शायद, शायद। – Cubic

+0

आप कोड को ब्रैकेट से घिरा सकते हैं। – MikeTheLiar

+0

'data = null' इसे कचरा-एकत्रित करने योग्य बनाता है। –

उत्तर

6

यह जेवीएम पर निर्भर करता है। ओरेकल के जेवीएम के संस्करण जो मैंने कोशिश की है (1.6.0_41 और 1.7.0_0 9) डिफ़ॉल्ट रूप से इस अनुकूलन को निष्पादित न करें। हालांकि, 1.7.0_0 9 आक्रामक अनुकूलन चालू होने पर इसे निष्पादित करता है।

यहाँ परीक्षण मैं आयोजित किया है:

public class Main { 
    public static int g() { 
     int n = 100000; 
     int arr[][] = new int[n][]; 
     for (int i = 0; i < n; ++i) { 
      try { 
       arr[i] = new int[100000]; 
      } catch (OutOfMemoryError ex) { 
       return i; 
      } 
     } 
     return -1; 
    } 
    public static void f1() { 
     int arr[] = new int[1000000]; 
     System.out.println(g()); 
    } 
    public static void f2() { 
     int arr[] = new int[1000000]; 
     arr = null; 
     System.out.println(g()); 
    } 
    public static void main(String[] argv) { 
     for (int j = 0; j < 2; ++j) { 
      for (int i = 0; i < 10; ++i) { 
       f1(); 
      } 
      System.out.println("-----"); 
      for (int i = 0; i < 10; ++i) { 
       f2(); 
      } 
      System.out.println("-----"); 
     } 
    } 
} 

डिफ़ॉल्ट सेटिंग के साथ JVM 1.7 का उपयोग करना, f1() लगातार स्मृति से बाहर 3195 पुनरावृत्तियों के बाद, चलाता है, जबकि f2() लगातार 3205 पुनरावृत्तियों प्रबंधन करता है।

यदि कोड जावा 1.7.0_09 -XX:+AggressiveOpts -XX:CompileThreshold=1 के साथ कोड चलाया जाता है तो चित्र बदलता है: दोनों संस्करण 3205 पुनरावृत्तियों कर सकते हैं, यह दर्शाता है कि हॉटस्पॉट इस मामले में इस अनुकूलन को निष्पादित करता है। जावा 1.6.0_41 ऐसा करने के लिए प्रतीत नहीं होता है।

मेरे परीक्षण में, सरणी के दायरे को प्रतिबंधित करने के संदर्भ में null को सेट करने के समान प्रभाव पड़ता है, और यदि आपको लगता है कि आपको जेवीएम को सरणी एएसएपी एकत्र करने में मदद करना चाहिए तो शायद पसंदीदा विकल्प होना चाहिए।

+0

क्या आपने आक्रामक ऑप्ट्स झंडे के साथ खेलने की कोशिश की है? – radai

+0

@radai: जो झंडे आप मन में क्या है? – NPE

+0

-XX: + AggressiveOpts -XX: CompileThreshold = 1 अधिकतर, इसे संकलित और अनुकूलित करने के लिए – radai

0

यदि डेटा का कोई संदर्भ नहीं है, तो जीसी नौकरी करेगा।

+0

यह सवाल का जवाब नहीं देता है। संपादित करें: मैं रास्ते से डाउनवॉटर नहीं हूं :) –

+0

वह क्या कह रहा है कि सरणी का संदर्भ गुंजाइश के भीतर मौजूद है, लेकिन इसका उपयोग प्रोग्राम के बाकी (लंबे समय तक चलने वाले) निष्पादन के लिए नहीं किया जाता है। मुझे लगता है कि सवाल बेहतर phrased किया जा सकता है: "यदि कोई संदर्भ मौजूद है लेकिन अप्रयुक्त है तो डेटा कचरा एकत्र किया जा सकता है?" – asteri

1

लिखित कोड को देखते हुए, सरणी निश्चित रूप से लंबे समय तक() निष्पादन के दौरान एकत्र कचरा नहीं होगी, क्योंकि स्टैक पर सरणी के लिए अभी भी एक स्कॉप्ड संदर्भ है। एक बार उस सरणी घोषित हो जाने के बाद, यह कचरा संग्रह के लिए योग्य नहीं होगा जब तक कि इसके सभी संदर्भ हटा दिए गए न हों। आपकी लाइन

data = null; 

इसके संदर्भ में एक संदर्भ हटा देगा, हालांकि आपके प्रोसेसिंग कोड के आधार पर यह एकमात्र संदर्भ नहीं हो सकता है। यदि सभी संदर्भ हटा दिए गए हैं, तो कचरा कलेक्टर लंबे समय तक() रिटर्न के समय उस सरणी की स्मृति को बहुत अच्छी तरह से एकत्र कर सकता है, हालांकि इसकी गारंटी नहीं है।

0

प्रक्रिया विधि समाप्त होने के बाद डेटा सरणी केवल स्मृति के साथ हटा दी जाएगी। इसलिए यदि आप संकलक को स्मृति को डिलीकेट करना चाहते हैं तो आपको कोड में डेटा = शून्य को स्पष्ट रूप से जोड़ना होगा।

कचरा कलेक्टर केवल उस स्मृति को मुक्त करता है जिसके पास वैध संदर्भ नहीं है और उस स्मृति को फिर से इंगित करने का कोई अन्य तरीका नहीं है।

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