2009-10-26 12 views
9

मेरे पास एक सर्वर घटक है जिसे मैं लोड-टेस्ट करने का प्रयास कर रहा हूं। सर्वर से सभी कनेक्शन टीएलएस 1.0 का उपयोग करते हैं।सूर्य का जावा एसएसएल कार्यान्वयन मेमोरी लीक कर रहा है?

Full TLS handshake to the server 
send a request 
read reply 
close connection 
repeat ad nauseam 

मेरे आभासी मशीन इस प्रकार है::

Java(TM) SE Runtime Environment (build 1.6.0_16-b01) 
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode) 

मैं एक स्मृति रिसाव है मैं एक साधारण परीक्षण कार्यक्रम है कि अनिवार्य रूप से के रूप में कई सूत्र पर यह करता है के रूप में मैं चाहता हूँ की है। मेरी मेमोरी पदचिह्न प्रति सेकंड लगभग 1 मेगापिक्सल बढ़ जाती है जब मैं अपने सर्वर का भारी परीक्षण करता हूं, जो इसे 15-20 मिनट के बाद OutOfMemoryException के साथ अवरुद्ध करता है।

मैंने इसे नेटबीन के प्रोफाइलर में भाग लिया और यह दिखाया कि स्मृति की वृद्धि टीएलएस एपीआई के भीतर गहरी थी।

क्या किसी ने कभी ऐसा कुछ अनुभव किया है? क्या कोई कामकाज है जो मैं अपने स्तर पर लागू कर सकता हूं?

संपादित करें।

.java.io.ByteArrayOutputStream.<init>(int) 
..com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte, int) 
...com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte) 
....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
.....com.sun.net.ssl.internal.ssl.SSLSocketImpl.init(com.sun.net.ssl.internal.ssl.SSLContextImpl, boolean) 
......com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(com.sun.net.ssl.internal.ssl.SSLContextImpl, java.net.Socket, String, int, boolean) 
.......com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(java.net.Socket, String, int, boolean) 
<my code> 

रहे हैं कई और अधिक मैं रख सकते हैं ... इस लंबी होगा: के रूप में अनुरोध किया है, यहाँ की रूपरेखा कॉल ट्रेस जो इन बाइट [] का एक बहुत उत्पन्न करता है। मैं तुम्हें प्रवेश बिंदुओं बता देंगे कि प्रोफाइलर मुझे देता है:

....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
....com.sun.net.ssl.internal.ssl.HandshakeOutStream.<init>(com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.HandshakeHash, com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
....com.sun.net.ssl.internal.ssl.SSLSocketImpl.sendAlert(byte, byte) 
..com.sun.net.ssl.internal.ssl.AppInputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
..com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake() 
..com.sun.net.ssl.internal.ssl.HandshakeInStream.<init>(com.sun.net.ssl.internal.ssl.HandshakeHash) 
+2

क्या आप कुछ और विशिष्ट प्रोफाइलिंग परिणाम प्रदान कर सकते हैं? रिसाव टीएलएस से जरूरी नहीं है, यह आपके कोड में हो सकता है। –

+1

कृपया इस छोटे से संभव प्रोग्राम को बनाएं जो इस व्यवहार को प्रदर्शित करता है और इसे आपके प्रश्न में जोड़ें। –

उत्तर

4

क्या आपने कनेक्शन को बंद कर दिया है। सबसे अधिक संभावना है कि यह अभी भी किसी भी तरह खुला है। 1 एमबी कुछ अतिरिक्त धागे का गायन है। हालांकि, मुझे यकीन नहीं है कि वास्तव में क्या कारण होगा।

+0

मैंने इसे देखा है। मैं 'execors.newScheduledTreadPool' का उपयोग कर रहा हूं, इसलिए मैं किसी भी समय किसी भी समय कितने धागे चल रहा हूं इस पर पूर्ण नियंत्रण में नहीं हूं। ऐसा कहा जा रहा है कि प्रोफाइलर के नतीजे बताते हैं कि अधिकांश मेमोरी बाइट [] द्वारा ली जाती है। – malaverdiere

+0

मैं दोबारा जांच करूंगा कि क्लाइंट डिस्कनेक्शन ठीक से संभाला जाता है और कनेक्शन बंद हो जाता है। अच्छा विचार। – malaverdiere

+0

यूप, जिसने एक बड़ा अंतर बनाया! भले ही डिस्कनेक्शन का पता लगाया गया था (IOException को पकड़कर), मैं SSLSocket बंद नहीं कर रहा था ... – malaverdiere

8

सभी SSL कनेक्शन एक SSL सत्र, जो अलग TCP कनेक्शन भर में पुन: उपयोग किया जा सकता है जब के बाद अस्थायी एन्क्रिप्शन कुंजी बातचीत हाथ मिलाना भूमि के ऊपर कम करने के लिए साथ जुड़े रहे हैं वास्तविक टीसीपी कनेक्शन स्थापित किया गया है। ऐसा हो सकता है कि आपके ग्राहक किसी भी नए सत्र के निर्माण को मजबूर कर रहे हों और चूंकि जावा 6 के लिए डिफ़ॉल्ट कॉन्फ़िगरेशन एक घंटे के लिए असीमित सत्रों को कैश करने के लिए प्रतीत होता है, तो आप आसानी से स्मृति समस्या में भाग ले सकते हैं।

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


क्या आप वाकई सही सत्र संदर्भ पर सीमा निर्धारित कर रहे हैं? मैं सर्वर सॉकेट से पहुंचने योग्य संदर्भ के बारे में गलत था। आप सर्वर सॉकेट बनाने से पहले SSLContext के माध्यम से यह स्थापित करने के लिए:

SSLContext sslContext = SSLContext.getDefault(); 
sslContext.getServerSessionContext().setSessionCacheSize(1000); 
SSLServerSocket ss = (SSLServerSocket) 
    sslContext.getServerSocketFactory().createServerSocket(<port>); 

इस सीमा के बिना, यह, अपनी स्मृति "रिसाव" पुन: पेश करने के रूप में प्रत्येक कैश्ड एसएसएल सत्र तेजी कहीं आसपास 7-800 बाइट का उपयोग करने के लिए आसान था ढेर स्मृति की। सत्र गिनती सीमा के साथ, मेरा सर्वर अब लगभग 15 मिनट तक तनाव में चल रहा है और अभी भी केवल 3-4 एमबी ढेर मेमोरी का उपयोग कर रहा है।

+0

मैंने 1000 सत्रों की सीमा निर्धारित की है। दुर्घटना से पहले वक्र पहले की तरह खड़ा नहीं है (यह अब सीढ़ियों की तरह दिखता है), इसलिए यह मदद कर रहा है। फिर भी, यह अभी भी दुर्घटनाग्रस्त है। – malaverdiere

+0

क्या आपने मेरे पोस्ट एडिट में सुझाए गए कोड स्निपेट का प्रयास किया है? – jarnbjo

+2

86400sec डिफ़ॉल्ट टाइमआउट (यानी 24h) है और आप डिफ़ॉल्ट कैश आकार सेट कर सकते हैं: w/'-Djavax.net.ssl.sessionCacheSize = xxx' प्रॉपर्टी – bestsss

1

1 एमबी एक धागा बनाने के लिए आवश्यक स्मृति है, अतिरिक्त या नहीं।

क्या उस कक्षा या पैकेज के लिए बग सूची में कोई प्रविष्टियां हैं? पहला कदम यह जांचना होगा।

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

यह कहना नहीं है कि जेडीके कोड बग-फ्री है, बस आपको पहले अपना कोड संदेह करना चाहिए।

एक प्रोफाइलर और उपाय प्राप्त करें। अनुमान मत करो।

+1

+1 - अपने स्वयं के कोड को पहले संदेह करें –

+0

जैसा कि मैंने कहा, मैं एक प्रोफाइलर में चला गया हूं। सभी ओवरहेड बाइट [] के कारण है जो एसएसएल कार्यान्वयन के भीतर गहराई से बनाया गया है। – malaverdiere

0

आप किस हार्डवेयर पर चल रहे हैं? क्या आप नेटस्टैट कर सकते हैं और अपने कनेक्शन की स्थिति को सत्यापित कर सकते हैं?

मैंने टॉमकैट का परीक्षण किया है, और सोलारिस पर 1 जीबी ढेर के साथ 500 नए एसएसएल अनुरोध/सेकंड, घंटों तक चलने में कोई परेशानी नहीं है। साथ ही, आप कंटेनर में चल रहे धागे की संख्या की निगरानी करना चाह सकते हैं।

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