exception - "Java.lang.OutOfMemoryError: PermGen space" त्रुटि से निपटना




memory-leaks out-of-memory (20)

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

java.lang.OutOfMemoryError: PermGen अंतरिक्ष

यह टॉमकैट 6 और जेडीके 1.6 पर चलने वाला एक विशिष्ट हाइबरनेट / जेपीए + आइसफेसेस / जेएसएफ एप्लीकेशन है। स्पष्ट रूप से यह कुछ बार एक अनुप्रयोग को फिर से तैनात करने के बाद हो सकता है।

इसका कारण क्या है और इससे बचने के लिए क्या किया जा सकता है? मैं समस्या को कैसे ठीक करूं?


1) PermGen मेमोरी आकार में वृद्धि

सबसे पहले जो कोई भी कर सकता है वह स्थायी पीढ़ी के ढेर के आकार को बड़ा बनाना है। यह सामान्य-एक्सएमएस (प्रारंभिक ढेर आकार सेट करें) और -एक्सएमएक्स (अधिकतम ढेर आकार सेट करें) जेवीएम तर्कों के साथ किया जा सकता है, जैसा कि बताया गया है, स्थायी पीढ़ी हीप स्पेस नियमित जावा हीप स्पेस से पूरी तरह अलग है, और ये तर्क सेट इस नियमित जावा ढेर अंतरिक्ष के लिए जगह। हालांकि, ऐसे ही तर्क हैं जिनका प्रयोग स्थायी पीढ़ी ढेर के आकार को बनाने के लिए (कम से कम सूर्य / ओपनजेडीके जेवीएमएस के साथ) किया जा सकता है:

 -XX:MaxPermSize=128m

डिफ़ॉल्ट 64 मीटर है।

2) स्वीपिंग सक्षम करें

इसके लिए अच्छी देखभाल करने का एक और तरीका कक्षाओं को उतारने की अनुमति देना है ताकि आपका पर्मोजेन कभी खत्म न हो:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

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

आप इस त्रुटि का विवरण पा सकते हैं।

http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html


  1. टॉमकैट की बिन निर्देशिका से टॉमकैट 7 डब्ल्यू खोलें या स्टार्ट मेनू में मॉनिटर टॉमकैट टाइप करें (एक टैब्ड विंडो विभिन्न सेवा जानकारी के साथ खुलती है)।
  2. जावा विकल्प टेक्स्ट क्षेत्र में इस पंक्ति को संलग्न करें:

    -XX:MaxPermSize=128m
    
  3. 1024 (वैकल्पिक) में प्रारंभिक मेमोरी पूल सेट करें।
  4. अधिकतम मेमोरी पूल 1024 (वैकल्पिक) पर सेट करें।
  5. ओके पर क्लिक करें।
  6. टॉमकैट सेवा को पुनरारंभ करें।

अगर आप अपने वेबएप में log4j का उपयोग कर रहे हैं, तो log4j documentation में यह पैराग्राफ देखें।

ऐसा लगता है कि यदि आप PropertyConfigurator.configureAndWatch("log4j.properties") का उपयोग कर रहे हैं, तो आप अपने वेबपैप को पूर्ववत करते समय मेमोरी लीक का कारण बनते हैं।


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


इन दिनों सबसे सरल जवाब जावा 8 का उपयोग करना है।

यह अब पर्मजेन स्पेस के लिए स्मृति को रिजर्व नहीं करता है, जिससे पर्मोजेन मेमोरी नियमित मेमोरी पूल के साथ मिलकर मिलती है।

ध्यान रखें कि आपको सभी गैर-मानक -XXPermGen...=... JVM स्टार्टअप पैरामीटर को हटाना होगा यदि आप जावा 8 को शिकायत नहीं करना चाहते हैं कि वे कुछ भी नहीं करते हैं।


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

-XX:+CMSClassUnloadingEnabled

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

-XX:+UseConcMarkSweepGC

ऐप सर्वर पर्मजेन त्रुटियां जो एकाधिक तैनाती के बाद होती हैं, वे आपके पुराने ऐप्स के क्लासलोडर्स में कंटेनर द्वारा आयोजित संदर्भों के कारण होने की संभावना होती हैं। उदाहरण के लिए, कस्टम लॉग स्तरीय क्लास का उपयोग करके ऐप सर्वर के क्लासलोडर द्वारा संदर्भों का आयोजन किया जाएगा। आप आधुनिक (जेडीके 6 +) जेवीएम विश्लेषण उपकरण जैसे जेएमएपी और जाट का उपयोग करके इन इंटर-क्लासलोडर लीक का पता लगा सकते हैं, यह देखने के लिए कि कौन से कक्षाएं आपके ऐप में जारी रहती हैं, और उनके उपयोग को फिर से डिजाइन या समाप्त कर देती हैं। सामान्य संदिग्ध डेटाबेस, लॉगर्स, और अन्य आधार-ढांचे-स्तर पुस्तकालय हैं।

क्लासलोडर लीक देखें : भयभीत "java.lang.OutOfMemoryError: PermGen space" अपवाद , और विशेष रूप से इसके अनुवर्ती पोस्ट


कमांड लाइन पैरामीटर का उपयोग करें -XX:MaxPermSize=128m एक सन जेवीएम के लिए -XX:MaxPermSize=128m (जाहिर है कि आपको जो भी आकार चाहिए, 128 को प्रतिस्थापित कर रहा है)।


टॉमकैट शुरू होने पर समाधान इन झंडे को JVM कमांड लाइन में जोड़ना था:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

आप टॉमकैट सेवा को बंद करके, फिर टॉमकैट / बिन निर्देशिका में जाकर और tomcat6w.exe चलाकर ऐसा कर सकते हैं। "जावा" टैब के अंतर्गत, "जावा विकल्प" बॉक्स में तर्क जोड़ें। "ठीक" पर क्लिक करें और फिर सेवा को पुनरारंभ करें।

अगर आपको कोई त्रुटि मिलती है तो निर्दिष्ट सेवा एक स्थापित सेवा के रूप में मौजूद नहीं है, आपको यह चलाना चाहिए:

tomcat6w //ES//servicename

जहां servicename सर्वर का नाम है जैसा कि services.msc में देखा गया है

स्रोत: एरिक के Agile उत्तर पर orx की टिप्पणी।


टोमकैट को अधिक मेमोरी असाइन करना उचित समाधान नहीं है।

सही समाधान है कि संदर्भ नष्ट हो गया है और फिर से बनाया गया है (गर्म तैनाती)। समाधान स्मृति रिसाव को रोकने के लिए है।

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

आप ServletContextListener बना सकते हैं और इसे अपने web.xml में कॉन्फ़िगर कर सकते हैं। यहां एक नमूना ServletContextListener है:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

/**
 * 
 * @author alejandro.tkachuk / calculistik.com
 *
 */
public class AppContextListener implements ServletContextListener {

    private static final Logger logger = Logger.getLogger(AppContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        logger.info("AppContextListener started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        logger.info("AppContextListener destroyed");

        // manually unregister the JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("Unregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error unregistering driver %s", driver), e);
            }

        }

        // manually shutdown clean up threads
        try {
            AbandonedConnectionCleanupThread.shutdown();
            logger.info("Shutting down AbandonedConnectionCleanupThread");
        } catch (InterruptedException e) {
            logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
            e.printStackTrace();
        }        
    }
}

और यहां आप इसे अपने web.xml में कॉन्फ़िगर करते हैं:

<listener>
    <listener-class>
        com.calculistik.mediweb.context.AppContextListener 
    </listener-class>
</listener>  

मुझे इसी तरह का मुद्दा था। मेरा जेडीके 7 + मेवेन 3.0.2 + स्ट्रूट्स 2.0 + Google GUICE निर्भरता इंजेक्शन आधारित प्रोजेक्ट है।

जब भी मैंने mvn clean package कमांड चलाने की कोशिश की, तो यह निम्नलिखित त्रुटि दिखा रहा था और "असफल असफलता" हुई

org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; नेस्टेड अपवाद java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException के कारण: java.lang.OutOfMemoryError: PermGen space

मैंने उपरोक्त सभी उपयोगी टिप्स और चाल की कोशिश की लेकिन दुर्भाग्य से मेरे लिए कोई भी काम नहीं किया। मेरे लिए क्या काम किया गया है नीचे दिए गए कदम से नीचे वर्णित है: =>

  1. अपने pom.xml पर जाएं
  2. <artifactId>maven-surefire-plugin</artifactId>
  3. एक नया <configuration> तत्व जोड़ें और फिर <argLine> उप तत्व जिसमें पास -Xmx512m -XX:MaxPermSize=256m जैसा नीचे दिखाया गया है =>

<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

उम्मीद है कि यह मदद करता है, खुश प्रोग्रामिंग :)


मुझे समस्या है कि हम यहां बात कर रहे हैं, मेरा परिदृश्य ग्रहण-हेलीओस + टोमकैट + जेएसएफ है और आप जो कर रहे थे वह टोमकैट को एक साधारण एप्लिकेशन तैनात कर रहा है। मैं यहां एक ही समस्या दिखा रहा था, इसे निम्नानुसार हल किया।

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

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

और त्यार।


मेरे लिए काम करने का एकमात्र तरीका जेआरॉकिट जेवीएम के साथ था। मेरे पास MyEclipse 8.6 है।

JVM का ढेर एक चल रहे जावा प्रोग्राम द्वारा उत्पन्न सभी ऑब्जेक्ट्स को स्टोर करता है। जावा वस्तुओं को बनाने के लिए new ऑपरेटर का उपयोग करता है, और नई वस्तुओं के लिए स्मृति को रन टाइम पर ढेर पर आवंटित किया जाता है। कचरा संग्रह उन वस्तुओं द्वारा निहित स्मृति को स्वचालित रूप से मुक्त करने का तंत्र है जिसे अब प्रोग्राम द्वारा संदर्भित नहीं किया जाता है।


मैं बिल्कुल एक ही समस्या में भागता हूं, लेकिन दुर्भाग्य से सुझाए गए समाधानों में से कोई भी वास्तव में मेरे लिए काम नहीं करता है। समस्या तैनाती के दौरान नहीं हुई थी, और मैं न तो कोई गर्म तैनाती कर रहा था।

मेरे मामले में समस्या मेरे वेब-एप्लिकेशन के निष्पादन के दौरान हर समय होती है, जबकि डेटाबेस (हाइबरनेट के माध्यम से) को डेटाबेस में कनेक्ट करते समय।

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


मैंने कई उत्तरों की कोशिश की और एकमात्र चीज जो आखिरकार काम करती थी, पोम में कंपाइलर प्लगइन के लिए यह कॉन्फ़िगरेशन था:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
        <source>1.6</source>
        <target>1.6</target>
        <!-- prevent PermGen space out of memory exception -->
        <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
    </configuration>
</plugin>

उम्मीद है कि यह मदद करता है।


यदि आप इसे ग्रहण आईडीई में प्राप्त कर रहे हैं, पैरामीटर सेट करने के बाद भी --launcher.XXMaxPermSize , -XX:MaxPermSize , आदि, फिर भी यदि आपको एक ही त्रुटि मिल रही है, तो संभवतः यह ग्रहण एक बग्गी संस्करण का उपयोग कर रहा है जेआरई का जो कुछ तीसरे पक्ष के अनुप्रयोगों द्वारा स्थापित किया गया था और डिफ़ॉल्ट रूप से सेट किया गया था। ये बग्गी संस्करण पर्मसाइज़ पैरामीटर नहीं उठाते हैं और इसलिए जो भी आप सेट करते हैं, कोई फर्क नहीं पड़ता, फिर भी आप इन मेमोरी त्रुटियों को प्राप्त करते रहते हैं। तो, अपने eclipse.ini में निम्नलिखित पैरामीटर जोड़ें:

-vm <path to the right JRE directory>/<name of javaw executable>

यह भी सुनिश्चित करें कि आपने जावा के सही संस्करण में ग्रहण में प्राथमिकता में डिफ़ॉल्ट जेआरई सेट किया है।


वे कहते हैं कि टोमकैट का नवीनतम संशोधन (6.0.28 या 6.0.2 9) सर्वलेट को पुन: नियोजित करने का कार्य बहुत बेहतर करता है।


वैकल्पिक रूप से, आप जेआरॉकिट पर स्विच कर सकते हैं जो कि सूरज के जेवीएम को अलग-अलग परमजन को संभालने में सक्षम होता है। यह आमतौर पर बेहतर प्रदर्शन भी करता है।

http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html


स्मृति की कॉन्फ़िगरेशन आपके ऐप की प्रकृति पर निर्भर करती है।

तुम क्या कर रहे हो?

लेनदेन की राशि कितनी है?

आप कितना डेटा लोड कर रहे हैं?

आदि।

आदि।

आदि

शायद आप अपने ऐप को प्रोफाइल कर सकते हैं और अपने ऐप से कुछ मॉड्यूल साफ़ करना शुरू कर सकते हैं।

स्पष्ट रूप से यह कुछ बार एक अनुप्रयोग को फिर से तैनात करने के बाद हो सकता है

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


java.lang.OutOfMemoryError: PermGen अंतरिक्ष संदेश इंगित करता है कि स्मृति में स्थायी पीढ़ी का क्षेत्र समाप्त हो गया है।

किसी भी जावा अनुप्रयोगों को सीमित मात्रा में स्मृति का उपयोग करने की अनुमति है। आपके विशेष एप्लिकेशन का उपयोग कर सकते हैं स्मृति की सटीक मात्रा एप्लिकेशन स्टार्टअप के दौरान निर्दिष्ट है।

जावा मेमोरी को विभिन्न क्षेत्रों में विभाजित किया गया है जो निम्न छवि में देखा जा सकता है:

मेटास्पेस: एक नई मेमोरी स्पेस पैदा होती है

जेडीके 8 हॉटस्पॉट जेवीएम अब वर्ग मेटाडेटा के प्रतिनिधित्व के लिए मूल स्मृति का उपयोग कर रहा है और इसे मेटास्पेस कहा जाता है; ओरेकल जेरॉकिट और आईबीएम जेवीएम के समान।

अच्छी खबर यह है कि इसका अर्थ यह नहीं है कि java.lang.OutOfMemoryError: PermGen अंतरिक्ष समस्याएं और Java_8_Download या उच्चतम का उपयोग करके अब इस मेमोरी स्पेस को ट्यून और मॉनीटर करने की आवश्यकता नहीं है।





permgen