2010-02-26 12 views
38

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

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

java.lang.ResourceBundle.clearCache(classLoader); 
org.apache.commons.logging.LogFactory.release(classLoader); 
java.beans.Introspector.flushCaches(); 

यहां तक ​​कि ऊपर कैश साफ़ करने के बाद, वर्ष classloader अभी भी कचरा एकत्र नहीं किया जा रहा था। classloader करने के लिए शेष संदर्भ निम्नलिखित शामिल हैं:

  • classloader द्वारा लोड कक्षाएं
  • java.lang.Package के classloader खुद के द्वारा बनाई गई
  • java.lang.ProtectionDomain classloader ही
  • द्वारा बनाई गई

उपरोक्त सभी क्लासलोडर के भीतर परिपत्र संदर्भ हैं, जो कचरा संग्रह को ट्रिगर करना चाहिए। मुझे यकीन नहीं है कि यह क्यों नहीं है। क्या किसी को पता है कि क्यों पुराने क्लासलोडर अभी भी परिपत्र संदर्भों के साथ कचरा नहीं जा रहे हैं?

+0

आप किस जेवीएम का उपयोग करते हैं (सटीक संस्करण)? क्या आप किसी भी JVM विकल्प का उपयोग करते हैं, जो क्लासलोडिंग को प्रभावित कर सकता है? क्या आप सूर्य के अपने कार्यान्वयन से किसी भी सामान का उपयोग करते हैं? क्या आवेदन बाइट कोड में हेरफेर करता है? ... पर्यावरण क्या है, जो वर्ग लोडिंग को प्रभावित कर सकता है? – cafebabe

+1

आपके मुख्य प्रश्न से संबंधित नहीं है, लेकिन क्या आपने अपने स्वयं के ढांचे को करने के बजाय ओएसजीआई की तरह कुछ विचार किया है जो गर्म तैनाती का समर्थन करता है? – SteveD

+0

@bfoo हमारे परीक्षणों में, हम जावा 6 का उपयोग कर रहे हैं। कोई JVM विकल्प नहीं।हम सबसे सरल मामले में सूर्य के प्रभाव का उपयोग नहीं कर रहे हैं। कोई बाइट कोड मैनिपुलेशन नहीं। – onejigtwojig

उत्तर

15

मैंने हमेशा सुना है कि Classloader अनलोडिंग समस्याग्रस्त थी। वे theoretically कचरा इकट्ठा होते हैं जब ऑब्जेक्ट इंस्टेंस और क्लास अनलोडिंग का संदर्भ नहीं होता है, लेकिन व्यवहार में यह अधिक समस्याग्रस्त होना प्रतीत होता है। सूक्ष्म संदर्भ रीसाइक्ड होने से Classloader को रिसाव और रोक सकते हैं। एप्लिकेशन सर्वर में, कई पुनर्वित्त चक्र के बाद, मुझे कभी-कभी OutOfMemoryError: PermGen space मिला।

यह सब कहने के लिए कि मुझे लगता है कि वहां एक बुरा संदर्भ है जो इसे एकत्र होने से रोकता है - शायद स्मृति विश्लेषक ने लिंक का सही ढंग से पालन नहीं किया। ऐसा लगता है कि यह सब, हो सकता है इन लेखों में बताए अनुसार लगता है:

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

मुझे आशा है कि यह आप में मदद मिलेगी।

+0

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

+0

ओह और वैसे, महान लिंक! – onejigtwojig

+0

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

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