क्या java.lang.StackOverflowError का कारण बनता है


86

क्या कारण हो सकते हैं java.lang.StackOverflowError? स्टैक प्रिंटआउट जो मुझे मिलता है वह बहुत गहरा नहीं है (केवल 5 तरीके)।


3
यह पोस्ट मदद कर सकती है: stackoverflow.com/questions/860550/…
जेक ग्रीन

जवाबों:


59

तरीकों के लिए किसी भी पुनरावर्ती कॉल की जाँच करें। मुख्य रूप से यह तब होता है जब किसी विधि के लिए पुनरावर्ती कॉल होता है। एक सरल उदाहरण है

public static void main(String... args) {
    Main main = new Main();

    main.testMethod(1);
}

public void testMethod(int i) {
    testMethod(i);

    System.out.println(i);
}

यहाँ System.out.println (i); जब TestMethod कहा जाता है तो बार-बार स्टैक करने के लिए धक्का दिया जाएगा।


1
मेरे विचार से आप सही है। लेकिन इसका हल क्या है। क्योंकि हम एक विधि बना रहे हैं, जिसका अर्थ है कि हमें इसकी आवश्यकता है। हम विधि में बदलाव नहीं करना चाहते हैं। तो इस त्रुटि को कैसे सुलझा सकते हैं?
अजय शर्मा

1
या आप एक अनंत पाश में हो रहे हैं!
येलमट्टा

@yalematta, किसी भी पुनरावर्ती विधि से बाहर निकलने के लिए एक शर्त होनी चाहिए। इसलिए जांचें कि क्या आपके पुनरावर्ती विधि को ठीक से लागू किया गया है और कुछ स्थिति पर निर्भर करता है।
अयाज अलीफोव

@ अजयशर्मा को उपलब्ध स्मृति सीमाओं में फिट होने के लिए हमें अपने सिस्टम को डिजाइन करने की आवश्यकता है जिसे हमने जेवीएम को सौंपा था। यदि सिस्टम निम्न त्रुटि के साथ अजीब व्यवहार करता है तो हमें अपने कोड आधार की जांच करने की आवश्यकता है।
थोथा श्रीनाथ

23

JVM के लिए (वैकल्पिक) तर्कों में से एक स्टैक आकार है। यह -Xss है। मुझे नहीं पता कि डिफ़ॉल्ट मान क्या है, लेकिन यदि स्टैक पर सामान की कुल मात्रा उस मूल्य से अधिक है, तो आपको वह त्रुटि मिलेगी।

आमतौर पर, अनंत पुनरावृत्ति इसका कारण है, लेकिन यदि आप देख रहे थे कि, आपके स्टैक ट्रेस में 5 से अधिक फ़्रेम होंगे।

यह देखने के लिए कि क्या यह चला जाता है, एक -Xss तर्क जोड़ने (या एक के मान को बढ़ाने) का प्रयास करें।


10

क्या वास्तव में एक java.lang.StackOverflowError का कारण बनता है, आमतौर पर अनजाने में पुनरावृत्ति होती है। मेरे लिए यह अक्सर होता है जब मैं ओवरड्यूड विधि के लिए एक सुपर विधि को कॉल करना चाहता हूं। जैसे कि इस मामले में:

public class Vehicle {
    public void accelerate(float acceleration, float maxVelocity) {
        // set the acceleration
    }
}

public class SpaceShip extends Vehicle {
    @Override
    public void accelerate(float acceleration, float maxVelocity) {
        // update the flux capacitor and call super.accelerate
        // oops meant to call super.accelerate(acceleration, maxVelocity);
        // but accidentally wrote this instead. A StackOverflow is in our future.
        this.accelerate(acceleration, maxVelocity); 
    }
}

सबसे पहले, यह जानना उपयोगी है कि जब हम किसी फ़ंक्शन को कहते हैं तो पर्दे के पीछे क्या होता है। तर्कों और उस पते का पता जहां विधि को बुलाया गया था, उसे स्टैक पर धकेल दिया गया है (देखें http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ) ताकि पुकार विधि तर्कों तक पहुंच सके और ताकि जब कहा जाता है विधि पूरी हो गई है, कॉल के बाद निष्पादन जारी रह सकता है। लेकिन चूँकि हम इसे कॉल कर रहे हैं। एक्सेलेरेट (एक्सेलेरेशन, मैक्सवेलोसिटी) रिकर्सिकली (पुनरावृत्ति शिथिल होती है जब कोई विधि खुद को कॉल करती है। अधिक जानकारी के लिए http://en.wikipedia.org/wiki/Recursion_computer_science देखें )) हम एक स्थिति में हैं जिसे अनंत पुनरावृत्ति के रूप में जाना जाता है और हम कॉल स्टैक पर तर्कों और रिटर्न एड्रेस को जमा करते रहते हैं। चूंकि कॉल स्टैक आकार में परिमित है, हम अंततः अंतरिक्ष से बाहर भागते हैं। कॉल स्टैक पर अंतरिक्ष से बाहर निकलने को अतिप्रवाह के रूप में जाना जाता है। ऐसा इसलिए है क्योंकि हम अपने पास अधिक स्टैक स्पेस का उपयोग करने की कोशिश कर रहे हैं और डेटा सचमुच स्टैक को ओवरफ्लो करता है। जावा प्रोग्रामिंग भाषा में, यह रनटाइम अपवाद java.lang.StackOverflow में परिणाम करता है और प्रोग्राम को तुरंत रोक देगा।

उपर्युक्त उदाहरण कुछ हद तक सरल है (हालाँकि यह मेरे साथ ऐसा होता है जितना मैं स्वीकार करना चाहता हूँ।) एक ही बात एक और दौर में हो सकती है जिस तरह से इसे ट्रैक करना थोड़ा कठिन होता है। हालांकि, सामान्य तौर पर, StackOverflow आमतौर पर इसे हल करने के लिए बहुत आसान है, एक बार ऐसा होता है।

सिद्धांत रूप में, पुनरावृत्ति के बिना एक स्टैक ओवरफ्लो होना भी संभव है, लेकिन व्यवहार में, यह काफी दुर्लभ घटना प्रतीत होगी।


8

क्या है java.lang.StackOverflowError

त्रुटि java.lang.StackOverflowErrorको यह इंगित करने के लिए फेंक दिया जाता है कि एप्लिकेशन का स्टैक समाप्त हो गया था, गहरी पुनरावृत्ति के कारण अर्थात आपका प्रोग्राम / स्क्रिप्ट बहुत गहराई से पुन: प्राप्त होता है।

विवरण

StackOverflowErrorफैली VirtualMachineErrorवर्ग जो इंगित करता है कि JVM किया गया है या संसाधनों समाप्त हो गया है और आगे काम नहीं कर सकते हैं। VirtualMachineErrorजो फैली Errorवर्ग उन गंभीर समस्या संकेत मिलता है कि एक आवेदन पत्र पकड़ नहीं चाहिए प्रयोग किया जाता है। एक विधि अपने throwखंड में ऐसी त्रुटियों की घोषणा नहीं कर सकती है क्योंकि ये त्रुटियां असामान्य स्थितियां हैं जिनके कभी होने की उम्मीद नहीं थी।

एक उदाहरण

Minimal, Complete, and Verifiable Example :

package demo;

public class StackOverflowErrorExample {

    public static void main(String[] args) 
    {
        StackOverflowErrorExample.recursivePrint(1);
    }

    public static void recursivePrint(int num) {
        System.out.println("Number: " + num);

        if(num == 0)
            return;
        else
            recursivePrint(++num);
    }

}

कंसोल आउटपुट

Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.StackOverflowError
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.PrintStream.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
    at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
    at java.io.PrintStream.newLine(Unknown Source)
    at java.io.PrintStream.println(Unknown Source)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
    .
    .
    .
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)

explaination

जब एक फ़ंक्शन कॉल जावा एप्लिकेशन द्वारा, एक स्टैक फ्रेम द्वारा लागू किया जाता है तो कॉल स्टैक पर आवंटित किया जाता है । इसमें stack frameशामिल विधि के पैरामीटर, इसके स्थानीय पैरामीटर और विधि का वापसी पता शामिल है। वापसी का पता निष्पादन बिंदु को दर्शाता है, जिसमें से आहरण विधि के वापस आने के बाद कार्यक्रम का निष्पादन जारी रहेगा। यदि नए स्टैक फ्रेम के लिए कोई स्थान नहीं है, तो StackOverflowErrorजावा वर्चुअल मशीन (जेवीएम) द्वारा फेंक दिया जाता है।

सबसे आम मामला जो संभवतः जावा एप्लिकेशन के स्टैक को समाप्त कर सकता है वह पुनरावृत्ति है। पुनरावृत्ति में, एक विधि अपने निष्पादन के दौरान खुद को आमंत्रित करती है। Recursionसबसे शक्तिशाली सामान्य-प्रयोजन प्रोग्रामिंग तकनीक में से एक है, लेकिन सावधानी बरतने के लिए सावधानी के साथ उपयोग किया StackOverflowErrorजाना चाहिए।

संदर्भ


4

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

वापसी का पता निष्पादन बिंदु को दर्शाता है, जिसमें से आहरण विधि के वापस आने के बाद कार्यक्रम का निष्पादन जारी रहेगा। यदि नए स्टैक फ्रेम के लिए कोई स्थान नहीं है, तो StackOverflowError को जावा वर्चुअल मशीन (JVM) द्वारा फेंक दिया जाता है

सबसे आम मामला जो संभवतः जावा एप्लिकेशन के स्टैक को समाप्त कर सकता है वह पुनरावृत्ति है।

कृपया एक नज़र डालें

StackOverflowError को कैसे हल करें


2

मैंने हाइबरनेट के साथ एक कार्यक्रम बनाया, जिसमें मैंने दो पीओजेओ कक्षाएं बनाईं, दोनों एक दूसरे के साथ डेटा सदस्यों के रूप में। जब मुख्य विधि में मैंने उन्हें डेटाबेस में सहेजने की कोशिश की तो मुझे भी यह त्रुटि मिली।

ऐसा इसलिए होता है क्योंकि दोनों वर्ग एक-दूसरे का उल्लेख कर रहे हैं, इसलिए एक लूप का निर्माण होता है जो इस त्रुटि का कारण बनता है।

इसलिए, जांचें कि आपके कार्यक्रम में इस तरह के संबंध मौजूद हैं या नहीं।


2

डेटा पार्स करते समय हाइबरनेट उपयोगकर्ताओं के लिए समाधान:

मेरे पास यह त्रुटि थी क्योंकि मैं दोनों तरफ मैप की गई वस्तुओं की सूची पार्स कर रहा था @OneToManyऔर@ManyToOne जैकसन का उपयोग करके जौंस कर जिसके कारण अनंत लूप बन गया।

यदि आप एक ही स्थिति में हैं, तो आप इसका उपयोग करके @JsonManagedReferenceऔर @JsonBackReferenceएनोटेशन द्वारा हल कर सकते हैं ।

एपीआई से परिभाषाएँ:

  • JsonManagedReference ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html ):

    एनोटेशन यह दर्शाता है कि एनोटेट संपत्ति खेतों के बीच दो-तरफ़ा लिंकेज का हिस्सा है; और इसकी भूमिका "माता-पिता" (या "आगे") लिंक है। संपत्ति के प्रकार (वर्ग) में एक एकल संगत संपत्ति होनी चाहिए जो कि JsonBackReference के साथ एनोटेट की गई हो। लिंकेज को ऐसे संभाला जाता है कि इस एनोटेशन के साथ एनोटेट की गई संपत्ति को सामान्य रूप से संभाला जाता है (सामान्य रूप से क्रमबद्ध, deserialization के लिए कोई विशेष हैंडलिंग नहीं); यह मिलान बैक संदर्भ है जिसे विशेष हैंडलिंग की आवश्यकता होती है

  • JsonBackReference: ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html ):

    यह इंगित करने के लिए उपयोग किया जाता है कि संबद्ध संपत्ति खेतों के बीच दो-तरफ़ा लिंकेज का हिस्सा है; और इसकी भूमिका "बच्चा" (या "पीछे") लिंक है। संपत्ति का मूल्य प्रकार एक बीन होना चाहिए: यह एक संग्रह, मानचित्र, सरणी या गणना नहीं हो सकता है। लिंकेज को ऐसे संभाला जाता है कि इस एनोटेशन के साथ एनोटेट की गई संपत्ति क्रमबद्ध नहीं है; और deserialization के दौरान, इसका मान "प्रबंधित" (आगे) लिंक वाले उदाहरण के लिए सेट किया गया है।

उदाहरण:

Owner.java:

@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;

Car.java:

@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;

एक अन्य समाधान का उपयोग करना है @JsonIgnoreजो बस क्षेत्र को शून्य सेट करेगा।


1

स्टैक ओवरफ़्लो अपवाद तब हो सकता है जब अधिकतम सीमा तक पहुंचने तक थ्रेड स्टैक आकार में बढ़ता रहता है।

स्टैक आकार (Xss और Xmso) विकल्पों को समायोजित करना ...

मेरा सुझाव है कि आप इस लिंक को देखें: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 StackOverflowError के कई संभावित कारण हैं, जैसा कि आप लिंक में देख सकते हैं ...।


लिंक केवल उत्तर आम तौर पर स्वीकार्य नहीं हैं; लिंक टूट जाता है जो पूरी तरह से उत्तर को अमान्य कर देगा। कृपया केवल लिंक के बजाय कुछ संदर्भ, कोड और उत्तर का स्पष्टीकरण प्रदान करें।
जय

0

मेरे मामले में मेरी दो गतिविधियाँ हैं। दूसरी गतिविधि में मैं ऑनक्रिएट विधि पर सुपर लगाना भूल गया।

super.onCreate(savedInstanceState);

यहां तक ​​कि अगर यह एक उठाने का एक संभावित तरीका है StackOverflowError, तो मैं यह नहीं कहता कि यह सवाल का जवाब दे रहा है। मुझे लगता है कि एक उचित उत्तर को या तो बहुत अधिक पुनरावृत्ति का उपयोग करने की तुलना में इस अपवाद को प्राप्त करने के लिए अन्य तरीकों को सूचीबद्ध करना चाहिए या यह कहें कि इस तरह के अपवाद को मैन्युअल रूप से फेंकने के अलावा कोई अन्य तरीका नहीं है।
जोजोतएक्सजीएमई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.