2008-09-17 12 views
27

मैं Log4J के साथ जावा 1.4 का उपयोग कर रहा हूं।क्या लॉग 4 जे लॉगर को क्षणिक घोषित किया जाना चाहिए?

मेरे कुछ कोड में मूल्य वस्तुएं (पीओजेओ) को क्रमबद्ध और deserializing शामिल है।

मेरी POJOs के

प्रत्येक

private final Logger log = Logger.getLogger(getClass()); 

के साथ एक लकड़हारा serializer की org.apache.log4j.Logger Serializable नहीं किया जा रहा शिकायत की घोषणा की।

मैं

private final transient Logger log = Logger.getLogger(getClass()); 

बजाय उपयोग करना चाहिए?

+1

कुछ प्रश्न जो आप अपने आप से पूछ सकते हैं और अपने प्रश्न में संपादित के रूप में जोड़ सकते हैं। इसे क्षणिक बनाने के लिए और आपके विचार क्या हैं? क्षणिक मतलब क्या है? – svrist

+1

मुझे उल्लेख करना चाहिए था, मुझे प्रत्येक वर्ग के लिए प्रत्येक उदाहरण के लिए लॉगर रखने का विचार पसंद है। मेरे पास एक ही कक्षा के तत्काल और प्रबंधित किए गए एक ही वर्ग के कई उदाहरण होंगे (एक स्प्रिंग एप्लिकेशन संदर्भ कहें) और प्रति-वर्ग आधार के बजाय प्रति-बीन आधार पर लॉगिंग स्तर स्विच करना चाहते हैं। स्प्रिंग एप्लिकेशन संदर्भ के उदाहरण में, लॉगर को निजी अंतिम क्षणिक लॉगर लॉग = Logger.getLogger (getBeanName()) के रूप में घोषित किया जाएगा; जहां बीन अब पीओजेओ नहीं है और बीननामएवेयर – Vihung

+1

लागू करता है [एसएलएफ 4 जे एफएक्यू] (http://www.slf4j.org/faq.html#declared_static): * "क्या किसी वर्ग के लॉगर सदस्यों को घोषित किया जाना चाहिए स्थैतिक? [...] संक्षेप में, स्थिर चर के रूप में लॉगर सदस्यों को घोषित करने के लिए कम CPU समय की आवश्यकता होती है और थोड़ा छोटी स्मृति पदचिह्न की आवश्यकता होती है। [...] हालांकि, आवृत्ति चर प्रत्येक एप्लिकेशन के लिए एक अलग लॉगर वातावरण बनाना संभव बनाता है, यहां तक ​​कि साझा पुस्तकालयों में घोषित लॉगर्स के लिए भी। शायद पहले उल्लिखित विचारों की तुलना में अधिक महत्वपूर्ण, आवृत्ति चर आईओसी-अनुकूल हैं जबकि स्थिर चर नहीं हैं। "* – Arjan

उत्तर

26

स्थिर लॉगर का उपयोग करने के बारे में कैसे? या क्या आपको कक्षा के प्रत्येक उदाहरण के लिए एक अलग लॉगर संदर्भ की आवश्यकता है? स्थिर फ़ील्ड डिफ़ॉल्ट रूप से क्रमबद्ध नहीं होते हैं; आप स्पष्ट रूप से नामक ObjectStreamField की निजी, स्थिर, अंतिम सरणी के साथ क्रमबद्ध करने के लिए फ़ील्ड घोषित कर सकते हैं। See Oracle documentation

जोड़ा गया सामग्री: जैसा कि आप getLogger(getClass()) का उपयोग करते हैं, आप प्रत्येक उदाहरण में एक ही लॉगर का उपयोग करेंगे। यदि आप प्रत्येक उदाहरण के लिए अलग लॉगर का उपयोग करना चाहते हैं तो आपको getLogger() -method में लॉगर के नाम पर अंतर करना होगा। जैसे getLogger (getClass()। getName() + हैशकोड())। इसके बाद आपको यह सुनिश्चित करने के लिए क्षणिक विशेषता का उपयोग करना चाहिए कि लॉगर क्रमबद्ध नहीं है।

+2

स्टेटिक लॉगर्स वेब अनुप्रयोग पुनर्वितरण के लिए अच्छा नहीं हैं। –

+0

@ ThorbjørnRavnAndersen क्या आप कृपया समझा सकते हैं, वेब ऐप पुनर्वितरण के लिए यह अच्छा क्यों नहीं है? या क्या यह मुद्दा वाइल्डफ्लि 8.2 जैसे नए एएस के साथ तय किया गया है और इसी तरह? – CSchulz

+5

स्थैतिक लॉगर्स की प्रवृत्ति होती है - जब तक कि आपका ऐप बहुत सावधानी से कोडित न हो - क्लास लोडर को पकड़ने के लिए ताकि वे कचरा एकत्र नहीं किया जा सके। यह उदाहरण में दिखाता है मेवेन के दौरान लगातार मेमोरी के उपयोग में वृद्धि होती है जो जावैक को मावेन द्वारा फोर्क किया जाता है। –

11

लॉगर स्थिर होना चाहिए; यह इसे गैर-धारावाहिक बना देगा।

लॉगर गैर स्थैतिक बनाने का कोई कारण नहीं है, जब तक कि आपके पास ऐसा करने का कोई मजबूत कारण न हो।

+4

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

+9

* "लॉगर गैर स्थैतिक बनाने का कोई कारण नहीं है, जब तक कि आपके पास ऐसा करने का कोई मजबूत कारण न हो।" * - इससे मेरा सिर विस्फोट हो जाता है! ;-) – Arjan

2

इसके बजाय लॉगर स्थिर बनाने का प्रयास करें। आपको धारावाहिकरण की परवाह नहीं है क्योंकि इसे कक्षा लोडर द्वारा नियंत्रित किया जाता है।

0

यदि आप लॉगर प्रति-उदाहरण होना चाहते हैं तो हाँ, यदि आप अपनी ऑब्जेक्ट्स को क्रमबद्ध करने जा रहे हैं तो आप इसे क्षणिक बनाना चाहते हैं। Log4J लॉगर्स serializable नहीं हैं, Log4J के संस्करण में नहीं, जो कि मैं वैसे भी उपयोग कर रहा हूं, इसलिए यदि आप अपने लॉगर फ़ील्ड को क्षणिक नहीं बनाते हैं तो आपको क्रमबद्धरण पर अपवाद प्राप्त होंगे।

0

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

2

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

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

5

या तो अपने लॉगर फ़ील्ड को स्थैतिक या क्षणिक के रूप में घोषित करें।

दोनों तरीकों से यह सुनिश्चित होता है कि writeObject() विधि serialization के दौरान आउटपुट स्ट्रीम में फ़ील्ड लिखने का प्रयास नहीं करेगी।

आमतौर पर लॉगर फ़ील्ड स्थैतिक घोषित किए जाते हैं, लेकिन यदि आपको इसे एक उदाहरण फ़ील्ड होने की आवश्यकता है तो इसे केवल क्षणिक घोषित करें, क्योंकि यह आमतौर पर किसी गैर-धारावाहिक क्षेत्र के लिए किया जाता है। Deserialization पर लॉगर फ़ील्ड शून्य हो जाएगा, हालांकि, आपको इसे ठीक से शुरू करने के लिए readObject() विधि को लागू करना होगा।

9

यदि आप वास्तव में क्षणिक दृष्टिकोण को देखना चाहते हैं तो आपको ऑब्जेक्ट deserialized होने पर लॉग को रीसेट करने की आवश्यकता होगी।

private void readObject(java.io.ObjectInputStream in) 
    throws IOException, ClassNotFoundException; 

Serializable के लिए javadocs इस विधि के बारे में जानकारी है: जिस तरह से ऐसा करने की विधि को लागू करने के लिए है।

इसके बारे में आपका कार्यान्वयन कुछ ऐसी दिखाई देगी:

private void readObject(java.io.ObjectInputStream in) 
    throws IOException, ClassNotFoundException { 
    log = Logger.getLogger(...); 
    in.defaultReadObject(); 
} 

आप ऐसा करते हैं तो ऐसा नहीं करते हैं लोग इन आपके वस्तु deserializing के बाद रिक्त हो जाएगा।

0

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

(दूसरों की तरह स्थिर या क्षणिक उपयोग का उल्लेख किया गया है)।

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