2009-11-30 17 views
7

मैं टॉमकैट में जावा वेब एप्लिकेशन चला रहा हूं। आवेदन नियमित अंतराल पर क्रॉन नौकरी को निर्धारित करने के लिए क्वार्ट्ज ढांचे का उपयोग करता है। इस क्रॉन नौकरी में 4+ एमबी एक्सएमएल फ़ाइल को पार्स करना शामिल है, जिसे मैं जेडीओएम एपीआई का उपयोग कर कर रहा हूं। एक्सएमएल फ़ाइल में लगभग 3600 नोड्स को पार्स किया जा सकता है और इसके परिणामस्वरूप डेटा डीबी में अपडेट किया जा सकता है जिसे मैं अनुक्रमिक रूप से कर रहा हूं।
फ़ाइल के लगभग आधा भाग पार्स करने के बाद, मेरा एप्लिकेशन आउट ऑफ़ मेमोरी अपवाद फेंकता है। इसका स्टैक ट्रेस है:जावा मेमोरी से बाहर अपवाद

Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]" java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOfRange(Arrays.java:3210) 
     at java.lang.String.<init>(String.java:216) 
     at java.lang.StringBuffer.toString(StringBuffer.java:585) 
     at org.netbeans.lib.profiler.server.ProfilerRuntimeMemory.traceVMObjectAlloc(ProfilerRuntimeMemory.java:170) 
     at java.lang.Throwable.getStackTraceElement(Native Method) 
     at java.lang.Throwable.getOurStackTrace(Throwable.java:590) 
     at java.lang.Throwable.getStackTrace(Throwable.java:582) 
     at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:155) 
     at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:135) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1603) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1590) 
     at java.lang.Thread.run(Thread.java:619) 
Exception in thread "*** JFluid Monitor thread ***" java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOf(Arrays.java:2760) 
     at java.util.Arrays.copyOf(Arrays.java:2734) 
     at java.util.Vector.ensureCapacityHelper(Vector.java:226) 
     at java.util.Vector.add(Vector.java:728) 
     at org.netbeans.lib.profiler.server.Monitors$SurvGenAndThreadsMonitor.updateSurvGenData(Monitors.java:230) 
     at org.netbeans.lib.profiler.server.Monitors$SurvGenAndThreadsMonitor.run(Monitors.java:169) 
Nov 30, 2009 2:22:05 PM org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor processChildren 
SEVERE: Exception invoking periodic operation: 
java.lang.OutOfMemoryError: Java heap space 
     at java.lang.StringCoding$StringEncoder.encode(StringCoding.java:232) 
     at java.lang.StringCoding.encode(StringCoding.java:272) 
     at java.lang.String.getBytes(String.java:946) 
     at java.io.UnixFileSystem.getLastModifiedTime(Native Method) 
     at java.io.File.lastModified(File.java:826) 
     at org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1175) 
     at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1269) 
     at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:296) 
     at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:118) 
     at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1337) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1601) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610) 
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1590) 
     at java.lang.Thread.run(Thread.java:619) 
ERROR [JobRunShell]: Job updateVendorData.quoteUpdate threw an unhandled Exception: 
java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOfRange(Arrays.java:3210) 
     at java.lang.String.<init>(String.java:216) 
     at java.lang.StringBuffer.toString(StringBuffer.java:585) 
     at org.apache.commons.dbcp.PoolingConnection$PStmtKey.hashCode(PoolingConnection.java:296) 
     at java.util.HashMap.get(HashMap.java:300) 
     at org.apache.commons.pool.impl.GenericKeyedObjectPool.decrementActiveCount(GenericKeyedObjectPool.java:1085) 
     at org.apache.commons.pool.impl.GenericKeyedObjectPool.returnObject(GenericKeyedObjectPool.java:882) 
     at org.apache.commons.dbcp.PoolablePreparedStatement.close(PoolablePreparedStatement.java:80) 
     at org.apache.commons.dbcp.DelegatingStatement.close(DelegatingStatement.java:168) 
     at com.netcore.smsapps.stock.db.CompanyDaoImpl.updateCompanyQuote(CompanyDaoImpl.java:173) 
     at com.netcore.smsapps.stock.vendor.MyirisVendor.readScripQuotes(MyirisVendor.java:159) 
     at com.netcore.smsapps.stock.update.StockUpdateData.execute(StockUpdateData.java:38) 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:207) 
     at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525) 
DEBUG [ExceptionHelper]: Detected JDK support for nested exceptions. 
ERROR [ErrorLogger]: Job (updateVendorData.quoteUpdate threw an exception. 
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.OutOfMemoryError: Java heap space] 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:216) 
     at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525) 
Caused by: java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOfRange(Arrays.java:3210) 
     at java.lang.String.<init>(String.java:216) 
     at java.lang.StringBuffer.toString(StringBuffer.java:585) 
     at org.apache.commons.dbcp.PoolingConnection$PStmtKey.hashCode(PoolingConnection.java:296) 
     at java.util.HashMap.get(HashMap.java:300) 
     at org.apache.commons.pool.impl.GenericKeyedObjectPool.decrementActiveCount(GenericKeyedObjectPool.java:1085) 
     at org.apache.commons.pool.impl.GenericKeyedObjectPool.returnObject(GenericKeyedObjectPool.java:882) 
     at org.apache.commons.dbcp.PoolablePreparedStatement.close(PoolablePreparedStatement.java:80) 
     at org.apache.commons.dbcp.DelegatingStatement.close(DelegatingStatement.java:168) 
     at com.netcore.smsapps.stock.db.CompanyDaoImpl.updateCompanyQuote(CompanyDaoImpl.java:173) 
     at com.netcore.smsapps.stock.vendor.MyirisVendor.readScripQuotes(MyirisVendor.java:159) 
     at com.netcore.smsapps.stock.update.StockUpdateData.execute(StockUpdateData.java:38) 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:207) 

इससे मेरा टॉमकैट भी दुर्घटनाग्रस्त हो जाता है। क्या आप समस्या का निदान करने में मेरी मदद कर सकते हैं। मैंने नेटबीन्स में भी प्रोफाइलिंग सक्षम की है लेकिन ऐसा लगता है कि यहां तक ​​कि दुर्घटनाग्रस्त भी है। मैंने टॉमकैट को आवंटित डिफ़ॉल्ट मेमोरी रखी है। क्या कोई स्मृति रिसाव हो रही है। मेरा डीबी पोस्टग्रेस है और जेडीके 1.6.0_15 है।

धन्यवाद, अमित

+4

इस और पिछले प्रश्नों के उत्तर का चयन करना न भूलें; आप पहले ही 7 प्रश्न बना चुके हैं और उनमें से कोई भी अच्छा जवाब नहीं दे रहा है? –

उत्तर

5

हर आप एक डोम का प्रयोग कर एक एक्सएमएल फ़ाइल को पार्स करने के लिए, आप एक ही आकार के बारे में उपयोग करें इसे संभाल करने के लिए होगा स्मृति और डोम बुनियादी ढांचे में पूरे फ़ाइल लोड होगी, इसलिए इसके बारे में दो बार का उपभोग करेंगे आपकी फ़ाइल आकार की तुलना में स्मृति।

आपको SAX, एक ईवेंट आधारित पार्सर का उपयोग करने की आवश्यकता होगी। हालांकि इसे पहली बार समझना मुश्किल हो सकता है, यह एक बहुत ही मेमोरी प्रभावी है, क्योंकि यह स्मृति वर्तमान पार्सिंग नोड में रखता है।

लगता है कि जावा में कुछ SAX कार्यान्वयन हैं, जैसे StAX, मुझे उम्मीद है कि इससे मदद मिलती है।

+0

हाय रूबेंस, मैं बड़े एक्सएमएल को पार्स करने के लिए जेडीओएम का उपयोग कर रहा हूं और यह आंतरिक रूप से सैक्स पार्सर का उपयोग करता है। मेरा पार्सिंग कोड है: SAXBuilder builder = नया SAXBuilder(); दस्तावेज़ दस्तावेज़ = builder.build (इनपुट संसाधन); तत्व elem = doc.getRootElement(); – Amit

+1

चूंकि आपका डोम पार्सर SAX का उपयोग करता है, आपको अनुक्रमिक रूप से अपने एक्सएमएल को पढ़ना चाहिए, और 'उपयोग करने से बचने के लिए ..',' // 'और सामान –

+0

स्टैक्स और एसएक्स अलग-अलग एपीआई हैं। हालांकि, वे दोनों स्मृति उपयोग को कम करने के लिए इस्तेमाल किया जा सकता है। (एसएएक्स कॉलबैक का उपयोग करता है, स्टैक्स उपयोगकर्ता कोड में अगली पार्सड टोकन के लिए पूछता है) –

0

क्या आप वाकई कोई रिकर्सिव सरणी प्रतिलिपि नहीं हैं, गलती से वहां छोड़े गए हैं? शायद विभिन्न धागे में?

+0

हाय लोरेन्ज़ोग, मैं इस उद्देश्य के लिए किसी भी थ्रेड का उपयोग नहीं कर रहा हूं, और कोई सरणी प्रतिलिपि नहीं है। मैं एक्सएमएल फ़ाइल को पार्स करने के लिए जेडीओएम का उपयोग कर रहा हूं और मुझे लगता है कि यह इसके क्रियान्वयन के लिए ऐरेलिस्ट का उपयोग करता है। क्या यह एक मुद्दा हो सकता है? क्या स्मृति रिसाव की कोई संभावना है? – Amit

0

मैं फ़ाइल के बारे में उस बिंदु को दूसरी बार दूंगा और डोम मेमोरी का एक बड़ा सौदा कर रहा है। मुझे यह भी आश्चर्य होता है कि जब मैं इसे देखता हूं:

ERROR [JobRunShell]: Job updateVendorData.quoteUpdate threw an unhandled Exception: 
    java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOfRange(Arrays.java:3210) 

यह कॉपी करने की क्या प्रतिलिपि है? मुझे आश्चर्य है कि आपके कोड में कुछ और बुरा चल रहा है या नहीं।

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

मैं VisualGC का उपयोग कर स्मृति को देखने का सुझाव देता हूं ताकि आप देख सकें कि क्या हो रहा है।

+0

वह प्रतिलिपि स्ट्रिंगबफर के आंतरिक हैं। – BalusC

+0

हाय डफी, आपके उत्तर के लिए धन्यवाद। क्या जेडीओएम आंतरिक रूप से इस प्रतिलिपि को कार्यान्वित कर सकता है? हमेशा मैंने एप्लिकेशन के लिए प्रोफाइलिंग सक्षम कर दी है और जीसी चलाने के बाद भी 2 कक्षाएं मौजूद हैं, वे org.postgresql.jdbc4.Jdbc4PrepareStatement और org.postgresql.jdbc4.Jdbc4ResultSet हैं। क्या ये एप्लिकेशन में मेमोरी लीक का कारण बन सकते हैं? – Amit

+0

हो सकता है। कोड के बिना नहीं बता सकते हैं, लेकिन यदि आप इन्हें ठीक से बंद नहीं कर रहे हैं तो आप संसाधनों को लीक कर सकते हैं जो आपको दुःख पहुंचाएंगे। – duffymo

2

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

आप इसके बजाय अधिक स्मृति कुशल XML पार्सर का उपयोग करने पर विचार कर सकते हैं, उदाहरण के लिए VTD-XML (homepage here, benchmarks here)।

1

क्या आपने अधिकतम ढेर आकार को बड़ा करने की कोशिश की है ताकि यह देखने के लिए कि समस्या अभी भी होती है या नहीं? यहां तक ​​कि एक रिसाव भी नहीं हो सकता है। यह हो सकता है कि डिफ़ॉल्ट ढेर आकार (विंडोज़ पर 64 एम मुझे लगता है) इस विशेष प्रक्रिया के लिए अपर्याप्त है।

मुझे लगता है कि मुझे लगभग हमेशा किसी भी एप्लिकेशन को देने की ज़रूरत है जो मैं टॉमकैट को अधिक ढेर कर रहा हूं और डिफॉल्ट की तुलना में जेन स्पेस चला रहा हूं या मैं स्मृति समस्याओं से बाहर हो जाऊंगा। अगर आपको मेमोरी सेटिंग्स को एडजस्ट करने में मदद की ज़रूरत है तो this question पर एक नज़र डालें।

+0

हाय जेसन, आपके उत्तर के लिए धन्यवाद। मैंने अपना ढेर आकार बढ़ाया और आवेदन ठीक काम किया। मैंने अपने आवेदन के लिए प्रोफाइलिंग सेट की है और प्रक्रिया पूरी होने के बाद, 2 प्रकार की लाइव आवंटित वस्तुओं को कचरा कलेक्टर द्वारा हटाया नहीं जा सकता है, वे org.postgresql.jdbc4.Jdbc4PrepareStatement और org.postgresql.jdbc4.Jdbc4ResultSet हैं। क्या ये एप्लिकेशन में मेमोरी लीक का कारण बन सकते हैं? – Amit

+0

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

+0

मेरी क्षमताओं में से सर्वश्रेष्ठ के साथ, मैंने ख्याल रखा है कि मैंने खोले गए सभी कनेक्शन बंद कर दिए हैं लेकिन समस्या अभी भी मौजूद है। क्या कोई तरीका है कि आप इस – Amit

0

आप अपना आवेदन इस प्रकार से चला सकते हैं: -XX: + HeapDumpOnOutOfMemoryError। यह जेवीएम को मेमोरी से बाहर होने पर हीप डंप का उत्पादन करेगा। आप कुछ ऐसा उपयोग कर सकते हैं जैसे: MAT या JHAT को देखने के लिए कि कौन सी ऑब्जेक्ट्स आयोजित की जा रही हैं। मैं उत्पन्न हेप डंप पर ग्रहण स्मृति विश्लेषक उपकरण (MAT) का उपयोग करने का सुझाव देता हूं क्योंकि यह उपयोग करने के लिए काफी सरल है: http://www.eclipse.org/mat/

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

9

अपने जेवीएम के लिए रैम आवंटन बढ़ाने का प्रयास करें। यह मदद करनी चाहिए।

  • जावा -> स्थापित JREs
  • का चयन ग्रहण के लिए

    फिक्स:: - - (ग्रहण> वरीयताओं मैक पर अपनी)> प्राथमिकताएं आप इस प्रकार

    1. विंडोज ग्रहण वरीयता में इस कॉन्फ़िगर कर सकते हैं जेआरई और डिफ़ॉल्ट VM तर्क फ़ील्ड प्रकार -Xmx1024M में
    2. पर क्लिक करें। (या आपकी स्मृति वरीयता, 1 जीबी रैम के लिए 1024)
    3. फिनिश या ओके पर क्लिक करें।
  • +1

    के साथ मेरी मदद कर सकते हैं धन्यवाद यह काम करता है –

    2

    आपको टोमकैट जेवीएम के परमजेन स्पेस में और स्थान आवंटित करना होगा।

    यह JVM तर्क के साथ किया जा सकता है: -XX:MaxPermSize=128m

    डिफ़ॉल्ट रूप से, PermGen अंतरिक्ष 64M है (और इसलिए यदि आप अपने classpath में (वर्ग) जार की एक बहुत कुछ है यह, सभी संकलित कक्षाओं में शामिल है, तो आप वास्तव में इस जगह को भर सकते हैं)।

    एक तरफ ध्यान दें पर, आप JVisualVM साथ PermGen अंतरिक्ष के आकार की निगरानी कर सकते हैं और आप भी YourKit Java Profiler

    3

    साथ अपनी सामग्री का निरीक्षण कर सकते अपने JVM के लिए राम आवंटन बढ़ा कर देखें। यह मदद करनी चाहिए। ग्रहण के लिए

    फिक्स: आप के रूप में इस प्रकार है

    विंडोज ग्रहण वरीयता में इस कॉन्फ़िगर कर सकते हैं -> प्राथमिकताएं (Mac पर अपनी: ग्रहण -> वरीयताओं) जावा -> स्थापित JREs JRE का चयन करें और डिफ़ॉल्ट पर संपादित करें पर क्लिक करें VM तर्क फ़ील्ड प्रकार --Xms256m -Xmx512m -XX: MaxPermSize = 512m -XX: PermSize = 128m। (या आपकी स्मृति वरीयता, 1 जीबी रैम के लिए 1024) खत्म या ठीक पर क्लिक करें।

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