जावा प्रभाव कचरा संग्रह में अशक्त करने के लिए वस्तुओं को निर्दिष्ट करता है?


85

क्या nullजावा में अप्रयुक्त वस्तु संदर्भ निर्दिष्ट करने से किसी भी औसत दर्जे में कचरा संग्रहण प्रक्रिया में सुधार होता है?

जावा (और C #) के साथ मेरे अनुभव ने मुझे सिखाया है कि वर्चुअल मशीन या जेआईटी कंपाइलर को आज़माने और बाहर करने के लिए अक्सर काउंटर सहज है, लेकिन मैंने सहकर्मियों को इस पद्धति का उपयोग करते हुए देखा है और मुझे उत्सुकता है कि क्या यह एक अच्छा अभ्यास है ऊपर या उन वूडू प्रोग्रामिंग अंधविश्वासों में से एक?

जवाबों:


66

आमतौर पर, नहीं।

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

आपको केवल स्पष्ट रूप से अशक्त करने की आवश्यकता है यदि आप जानते हैं कि यह अन्यथा संदर्भित रहेगा। उदाहरण के लिए एक सरणी जो चारों ओर रखी जाती है। जब आप अब आवश्यक नहीं हैं, तो आप सरणी के व्यक्तिगत तत्वों को शून्य करना चाहते हैं।

उदाहरण के लिए, ArrayList का यह कोड:

public E remove(int index) {
    RangeCheck(index);

    modCount++;
    E oldValue = (E) elementData[index];

    int numMoved = size - index - 1;
    if (numMoved > 0)
         System.arraycopy(elementData, index+1, elementData, index,
             numMoved);
    elementData[--size] = null; // Let gc do its work

    return oldValue;
}

इसके अलावा, किसी वस्तु को स्पष्ट रूप से खींचने से किसी वस्तु को जल्द से जल्द एकत्र करने का कारण नहीं बनेगा, अगर वह केवल प्राकृतिक रूप से तब तक दायरे से बाहर जाती है जब तक कोई संदर्भ नहीं रहता है।

दोनों:

void foo() {
   Object o = new Object();
   /// do stuff with o
}

तथा:

void foo() {
   Object o = new Object();
   /// do stuff with o
   o = null;
}

कार्यात्मक रूप से समतुल्य हैं।


7
आप उन तरीकों के संदर्भों को भी शून्य करना चाहते हैं जो बड़ी मात्रा में मेमोरी का उपयोग कर सकते हैं या निष्पादित करने में लंबा समय ले सकते हैं, या एक स्विंग एप्लिकेशन में कोड में जो लंबे समय तक चल सकता है। कम तरीकों या छोटी जीवित वस्तुओं में, इसके अतिरिक्त भ्रामक कोड के लायक नहीं है।
जॉन गार्डनर

1
तो क्या यह सही है, जब हम किसी वस्तु को शून्य करते हैं, तो कूड़ा उठाने वाला उस वस्तु को तुरंत इकट्ठा कर लेता है ??
मुहम्मद बाबर

1
नहीं। कचरा संग्राहक को समय-समय पर यह देखने के लिए निष्पादित किया जाता है कि क्या कोई ऐसी वस्तुएं थीं जिनके लिए कोई संदर्भ चर इंगित नहीं कर रहे हैं। जब आप उन्हें शून्य करने के लिए सेट करते हैं और फिर कॉल करते हैं System.gc()तो इसे हटा दिया जाएगा (बशर्ते उस वस्तु की ओर कोई अन्य संदर्भ न हो)।
JavaTechnical

2
@JavaTechnical जैसा कि मुझे पता है कि यह गारंटी नहीं है कि System.gc () से कचरा संग्रहण शुरू होता है।
जैक

12

मेरे अनुभव में, अधिक बार नहीं, लोगों ने व्यामोह से बाहर के संदर्भों को जरूरी नहीं समझा। यहाँ एक त्वरित दिशानिर्देश है:

  1. यदि ऑब्जेक्ट A संदर्भ ऑब्जेक्ट B और आपको अब इस संदर्भ की आवश्यकता नहीं है और ऑब्जेक्ट A कचरा संग्रहण के लिए योग्य नहीं है, तो आपको स्पष्ट रूप से फ़ील्ड को खाली करना चाहिए। यदि संलग्न वस्तु को वैसे भी कचरा एकत्र किया जा रहा है, तो किसी क्षेत्र को शून्य करने की आवश्यकता नहीं है। एक निपटान () विधि में खेतों को बाहर निकालना लगभग हमेशा बेकार है।

  2. एक विधि में निर्मित वस्तु संदर्भों को शून्य करने की आवश्यकता नहीं है। विधि समाप्त होने के बाद वे अपने आप साफ हो जाएंगे। इस नियम का अपवाद यदि आप बहुत लंबी विधि या कुछ बड़े पैमाने पर लूप में चल रहे हैं और आपको यह सुनिश्चित करने की आवश्यकता है कि विधि के अंत से पहले कुछ संदर्भ साफ हो जाएं। फिर, ये मामले अत्यंत दुर्लभ हैं।

मैं कहूंगा कि अधिकांश समय आपको संदर्भों को शून्य करने की आवश्यकता नहीं होगी। कचरा संग्रहकर्ता को बाहर करने की कोशिश करना बेकार है। आप सिर्फ अक्षम, अपठनीय कोड के साथ समाप्त होंगे।


11

अच्छा लेख आज का कोडिंग हॉरर है

जिस तरह से जीसी का काम उन वस्तुओं की तलाश है, जिनके पास कोई संकेत नहीं है, उनकी खोज का क्षेत्र ढेर / स्टैक है और उनके पास कोई अन्य रिक्त स्थान है। इसलिए यदि आप एक चर को शून्य करने के लिए सेट करते हैं, तो वास्तविक वस्तु अब किसी के द्वारा इंगित नहीं की जाती है, और इसलिए GC'd हो सकती है।

लेकिन चूंकि GC उस सटीक इंस्टेंट पर नहीं चल सकता है, इसलिए आप वास्तव में अपने आप को कुछ भी नहीं खरीद सकते हैं। लेकिन अगर आपकी विधि काफी लंबी है (निष्पादन समय के संदर्भ में) तो यह इसके लायक हो सकता है क्योंकि आप उस वस्तु को इकट्ठा करने वाले जीसी के अपने अवसरों को बढ़ा रहे होंगे।

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

इसलिए सारांश में, हाँ यह मदद कर सकता है, लेकिन यह निर्धारक नहीं होगा



सुरक्षित अनुकूलन पर अच्छा बिंदु जो रेफरी को शून्य करने के लिए लाइन को हटा देता है।
asgs

8

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

Foo bar = new Foo();

आप दो काम करते हैं: पहला, आप किसी ऑब्जेक्ट का संदर्भ बनाते हैं, और दूसरा, आप फू ऑब्जेक्ट को स्वयं बनाते हैं। जब तक कि संदर्भ या कोई अन्य मौजूद है, तब तक विशिष्ट वस्तु gc'd नहीं हो सकती। हालाँकि, जब आप उस संदर्भ में अशक्त होते हैं ...

bar = null ;

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


12
लेकिन स्कोप से बाहर जाने से कोड की अतिरिक्त लाइन के बिना भी यही काम होगा। यदि यह एक विधि के लिए स्थानीय है, तो कोई आवश्यकता नहीं है। एक बार जब आप विधि छोड़ देते हैं, तो ऑब्जेक्ट GC के लिए योग्य होगा।
duffymo

2
अच्छा। अब, एक पॉप क्विज़ के लिए, कोड का एक उदाहरण बनाएं जिसके लिए यह पर्याप्त नहीं है। संकेत: वे मौजूद हैं।
चार्ली मार्टिन

7

निर्भर करता है।

आम तौर पर कम बोलने वाले आप अपनी वस्तुओं के संदर्भ रखते हैं, तेजी से वे एकत्र हो जाएंगे।

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

वैसे भी, डिफ़ॉल्ट रूप से अशक्त करने के लिए सभी संदर्भों की स्थापना मेरे लिए समय से पहले अनुकूलन है और किसी को भी इसे तब तक नहीं करना चाहिए जब तक कि विशिष्ट दुर्लभ मामलों में नहीं होता है, जहां यह याददाश्त में कमी हो जाती है।


6

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

आम तौर पर अशक्त करने के लिए संदर्भ सेट करना, कोड के READER से मतलब है कि यह ऑब्जेक्ट पूरी तरह से किया गया है और किसी भी अधिक के बारे में चिंतित नहीं होना चाहिए।

एक समान प्रभाव ब्रेसिज़ के एक अतिरिक्त सेट में डालकर एक संकीर्ण गुंजाइश पेश करके प्राप्त किया जा सकता है

{
  int l;
  {  // <- here
    String bigThing = ....;
    l = bigThing.length();
  }  // <- and here
}

यह नेगटेड ब्रेसिज़ को छोड़ने के बाद बिगथिंग को कचरा एकत्र करने की अनुमति देता है।


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

5
public class JavaMemory {
    private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);

    public void f() {
        {
            byte[] data = new byte[dataSize];
            //data = null;
        }

        byte[] data2 = new byte[dataSize];
    }

    public static void main(String[] args) {

        JavaMemory jmp = new JavaMemory();
        jmp.f();

    }

}

कार्यक्रम के ऊपर फेंकता है OutOfMemoryError। यदि आप असहजता करते हैं data = null;, तो OutOfMemoryErrorहल किया जाता है। अप्रयुक्त चर को शून्य करने के लिए सेट करना हमेशा अच्छा अभ्यास होता है


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

बाइट [] एरे कचरा को उस समय क्यों नहीं एकत्र किया जाता है, जब चर डेटा दायरे से बाहर हो?
ग्रावि

2
@ ग्रेव: दायरे से बाहर जाने की गारंटी नहीं है कि कचरा कलेक्टर स्थानीय वस्तुओं को इकट्ठा करेगा। हालाँकि, इसे शून्य करने के लिए सेट करना आउटऑफ़मैरी अपवाद को रोकता है, क्योंकि आपको गारंटी है कि जीसी आउटऑफ़मेरी अपवाद को फेंकने से पहले चलेगा, और यदि ऑब्जेक्ट शून्य करने के लिए सेट किया गया था तो यह संग्रहणीय होगा।
स्टेफानोस टी। जूल

यह भी देखें stackoverflow.com/questions/31260594/...
Raedwald

4

मैं एक बार एक वीडियो कॉन्फ्रेंसिंग एप्लिकेशन पर काम कर रहा था और जब मुझे ऑब्जेक्ट की आवश्यकता नहीं थी, तो जैसे ही मैंने संदर्भों को शून्य करने के लिए समय लिया, प्रदर्शन में एक बड़ा भारी अंतर देखा। यह 2003-2004 में था और मैं केवल कल्पना कर सकता हूं कि जीसी ने और भी होशियार हो गया है। मेरे मामले में मेरे पास हर सेकंड सैकड़ों वस्तुएं आ रही थीं और निकल रही थीं, इसलिए मैंने समय-समय पर किक मारते हुए जीसी को देखा। हालाँकि, जब मैंने इसे ऑब्जेक्ट्स को शून्य करने के लिए एक बिंदु बनाया, तो GC ने मेरे आवेदन को रोक दिया।

तो यह निर्भर करता है कि आपका क्या करना है ...


2

हाँ।

"द प्रोगैमैटिक प्रोग्रामर" से p.292:

NULL का संदर्भ सेट करके आप ऑब्जेक्ट की संख्या को एक से कम कर देते हैं ... (जो कचरा संग्रहकर्ता को इसे हटाने की अनुमति देगा)


मुझे लगता है कि यह केवल तभी लागू होता है जब संदर्भ गणना में अहंकार होता है। उपयोग में है या अन्यथा भी?
नृज

3
यह सलाह किसी भी आधुनिक कचरा संग्रहकर्ता के लिए अप्रचलित है; और संदर्भ जीसी की महत्वपूर्ण समस्याएं हैं, जैसे कि परिपत्र संदर्भ।
लॉरेंस डोल

यह भी एक निशान में सच होगा और जीसी को स्वीप करेगा; शायद अन्य सभी में। तथ्य यह है कि आपके पास एक कम संदर्भ है इसका मतलब यह नहीं है कि यह संदर्भ गिना जाता है। चिकोटी का जवाब यह बताता है। NULL से सेट की गुंजाइश कम करना बेहतर है।

1

मुझे लगता है कि ओपी इस तरह की चीजों का जिक्र कर रहा है:

private void Blah()
{
    MyObj a;
    MyObj b;

    try {
        a = new MyObj();
        b = new MyObj;

        // do real work
    } finally {
        a = null;
        b = null;
    }
}

इस मामले में, जैसे ही वे गुंजाइश छोड़ते हैं, VM उन्हें GC के लिए चिन्हित नहीं करेंगे?

या, एक अन्य दृष्टिकोण से, स्पष्ट रूप से आइटम सेट करने के लिए शून्य करने के लिए उन्हें शून्य करने के लिए कारण होगा, इससे पहले कि वे बस दायरे से बाहर चले गए? यदि ऐसा है, तो वीएम समय-समय पर जीसी को वस्तु खर्च कर सकता है, जब मेमोरी को किसी भी तरह की आवश्यकता नहीं होती है, जो वास्तव में खराब प्रदर्शन सीपीयू उपयोग वार का कारण होगा, क्योंकि यह अधिक पहले GC'ing होगा।


जिस समय जीसी चलता है वह गैर-नियतात्मक होता है। मुझे विश्वास नहीं है कि nullजीसी व्यवहार को प्रभावित करने के लिए एक वस्तु की स्थापना बिल्कुल नहीं है ।
३२:०२

0

" यह पता है "

मुझे जावा के बारे में पता नहीं है लेकिन .net (C #, VB.net ...) में आमतौर पर एक नल को असाइन करने की आवश्यकता नहीं होती है जब आपको किसी ऑब्जेक्ट की आवश्यकता नहीं होती है।

हालांकि ध्यान दें कि यह "आमतौर पर आवश्यक नहीं है"।

अपने कोड का विश्लेषण करके .net कंपाइलर चर के जीवन काल का एक अच्छा मूल्यांकन करता है ... जब वस्तु का उपयोग अब नहीं किया जा रहा है, तो इसे सटीक रूप से बताएं। इसलिए यदि आप obj = null लिखते हैं, तो यह वास्तव में ऐसा लग सकता है जैसे कि अभी भी obj का उपयोग किया जा रहा है ... इस मामले में यह एक शून्य असाइन करने के लिए काउंटर उत्पादक है।

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

इसके लिए कोई कठिन और तेज़ नियम नहीं है। उपरोक्त स्थान पर जाकर अपने कोड में अशक्त-कार्य करते हैं और यह देखने के लिए एक प्रोफाइलर चलाते हैं कि क्या यह किसी भी तरह से मदद करता है। सबसे शायद आप एक लाभ नहीं देख सकते हैं।

यदि यह .net कोड है जिसे आप ऑप्टिमाइज़ करने की कोशिश कर रहे हैं, तो मेरा अनुभव यह रहा है कि डिस्पोज़ और फ़ाइनलीज़ तरीकों के साथ अच्छी देखभाल करना वास्तव में नल के बारे में परेशान करने से ज्यादा फायदेमंद है।

विषय पर कुछ संदर्भ:

http://blogs.msdn.com/csharpfaq/archive/2004/03/26/97229.aspx

http://weblogs.asp.net/pwilson/archive/2004/02/20/77422.aspx


0

यहां तक ​​कि अगर संदर्भ को अशक्त करना थोड़ा और अधिक कुशल था, तो क्या यह आपके बदसूरत भुलक्कड़पन के साथ अपने कोड को मिर्ची करने की कुरूपता के लायक होगा? वे केवल अव्यवस्थित होंगे और उस आशय कोड को अस्पष्ट करेंगे जिसमें वे शामिल हैं।

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


0

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

क्या यह वूडू है? कथित तौर पर जावा लाइब्रेरी कोड के कुछ हिस्से हैं जो ऐसा करते हैं। उस कोड के लेखक औसत प्रोग्रामर की तुलना में बहुत बेहतर हैं और या तो जानते हैं, या सहयोग करते हैं, प्रोग्रामर जो कचरा कलेक्टर कार्यान्वयन के विवरण जानते हैं। ताकि पता चलता है वहाँ है कभी कभी एक लाभ।


0

जैसा कि आपने कहा कि अनुकूलन हैं, यानी जेवीएम उस जगह को जानता है जब चर को अंतिम रूप से इस्तेमाल किया गया था और इसके द्वारा संदर्भित वस्तु को इस अंतिम बिंदु (अभी भी वर्तमान दायरे में निष्पादित) के बाद जीसीड किया जा सकता है। तो ज्यादातर मामलों में संदर्भों को शून्य करने से GC को मदद नहीं मिलती है।

लेकिन "नेपोटिज्म" (या "फ्लोटिंग कचरा") की समस्या से बचने के लिए यह उपयोगी हो सकता है ( यहां अधिक पढ़ें या वीडियो देखें )। समस्या मौजूद है क्योंकि ढेर पुरानी और युवा पीढ़ियों में विभाजित है और वहाँ अलग-अलग जीसी तंत्र लागू होते हैं: माइनर जीसी (जो युवा जीन को साफ करने के लिए अक्सर होता है) और मेजर जीसी (जो पुराने जीन को साफ करने के लिए लंबे समय तक रुकने का कारण बनता है)। "नेपोटिज्म" यंग जीन में कचरा एकत्र करने की अनुमति नहीं देता है यदि यह कचरा द्वारा संदर्भित किया जाता है जो पहले से ही एक पुराने जीन के लिए कार्यकाल था।

यह 'पैथोलॉजिकल' है क्योंकि किसी भी प्रोन्नत नोड के परिणामस्वरूप सभी निम्नलिखित नोड्स को बढ़ावा मिलेगा जब तक कि कोई जीसी समस्या का समाधान नहीं करता है।

भाई-भतीजावाद से बचने के लिए यह एक अच्छा विचार है कि किसी ऑब्जेक्ट से संदर्भों को हटा दिया जाए जिसे हटाया जाना चाहिए। : आप इस तकनीक JDK कक्षाओं में लागू देख सकते हैं LinkedList और LinkedHashMap

private E unlinkFirst(Node<E> f) {
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null; // help GC
    // ...
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.