क्या कारण हो सकते हैं java.lang.StackOverflowError
? स्टैक प्रिंटआउट जो मुझे मिलता है वह बहुत गहरा नहीं है (केवल 5 तरीके)।
जवाबों:
तरीकों के लिए किसी भी पुनरावर्ती कॉल की जाँच करें। मुख्य रूप से यह तब होता है जब किसी विधि के लिए पुनरावर्ती कॉल होता है। एक सरल उदाहरण है
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 कहा जाता है तो बार-बार स्टैक करने के लिए धक्का दिया जाएगा।
JVM के लिए (वैकल्पिक) तर्कों में से एक स्टैक आकार है। यह -Xss है। मुझे नहीं पता कि डिफ़ॉल्ट मान क्या है, लेकिन यदि स्टैक पर सामान की कुल मात्रा उस मूल्य से अधिक है, तो आपको वह त्रुटि मिलेगी।
आमतौर पर, अनंत पुनरावृत्ति इसका कारण है, लेकिन यदि आप देख रहे थे कि, आपके स्टैक ट्रेस में 5 से अधिक फ़्रेम होंगे।
यह देखने के लिए कि क्या यह चला जाता है, एक -Xss तर्क जोड़ने (या एक के मान को बढ़ाने) का प्रयास करें।
क्या वास्तव में एक 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 आमतौर पर इसे हल करने के लिए बहुत आसान है, एक बार ऐसा होता है।
सिद्धांत रूप में, पुनरावृत्ति के बिना एक स्टैक ओवरफ्लो होना भी संभव है, लेकिन व्यवहार में, यह काफी दुर्लभ घटना प्रतीत होगी।
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)
जब एक फ़ंक्शन कॉल जावा एप्लिकेशन द्वारा, एक स्टैक फ्रेम द्वारा लागू किया जाता है तो कॉल स्टैक पर आवंटित किया जाता है । इसमें stack frame
शामिल विधि के पैरामीटर, इसके स्थानीय पैरामीटर और विधि का वापसी पता शामिल है। वापसी का पता निष्पादन बिंदु को दर्शाता है, जिसमें से आहरण विधि के वापस आने के बाद कार्यक्रम का निष्पादन जारी रहेगा। यदि नए स्टैक फ्रेम के लिए कोई स्थान नहीं है, तो StackOverflowError
जावा वर्चुअल मशीन (जेवीएम) द्वारा फेंक दिया जाता है।
सबसे आम मामला जो संभवतः जावा एप्लिकेशन के स्टैक को समाप्त कर सकता है वह पुनरावृत्ति है। पुनरावृत्ति में, एक विधि अपने निष्पादन के दौरान खुद को आमंत्रित करती है। Recursion
सबसे शक्तिशाली सामान्य-प्रयोजन प्रोग्रामिंग तकनीक में से एक है, लेकिन सावधानी बरतने के लिए सावधानी के साथ उपयोग किया StackOverflowError
जाना चाहिए।
जब कोई फ़ंक्शन कॉल जावा एप्लिकेशन द्वारा मंगाई जाती है, तो कॉल स्टैक पर स्टैक फ्रेम आवंटित किया जाता है। स्टैक फ्रेम में आह्वान विधि के पैरामीटर, इसके स्थानीय पैरामीटर और विधि का वापसी पता होता है।
वापसी का पता निष्पादन बिंदु को दर्शाता है, जिसमें से आहरण विधि के वापस आने के बाद कार्यक्रम का निष्पादन जारी रहेगा। यदि नए स्टैक फ्रेम के लिए कोई स्थान नहीं है, तो StackOverflowError को जावा वर्चुअल मशीन (JVM) द्वारा फेंक दिया जाता है ।
सबसे आम मामला जो संभवतः जावा एप्लिकेशन के स्टैक को समाप्त कर सकता है वह पुनरावृत्ति है।
कृपया एक नज़र डालें
मैंने हाइबरनेट के साथ एक कार्यक्रम बनाया, जिसमें मैंने दो पीओजेओ कक्षाएं बनाईं, दोनों एक दूसरे के साथ डेटा सदस्यों के रूप में। जब मुख्य विधि में मैंने उन्हें डेटाबेस में सहेजने की कोशिश की तो मुझे भी यह त्रुटि मिली।
ऐसा इसलिए होता है क्योंकि दोनों वर्ग एक-दूसरे का उल्लेख कर रहे हैं, इसलिए एक लूप का निर्माण होता है जो इस त्रुटि का कारण बनता है।
इसलिए, जांचें कि आपके कार्यक्रम में इस तरह के संबंध मौजूद हैं या नहीं।
डेटा पार्स करते समय हाइबरनेट उपयोगकर्ताओं के लिए समाधान:
मेरे पास यह त्रुटि थी क्योंकि मैं दोनों तरफ मैप की गई वस्तुओं की सूची पार्स कर रहा था @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
जो बस क्षेत्र को शून्य सेट करेगा।
स्टैक ओवरफ़्लो अपवाद तब हो सकता है जब अधिकतम सीमा तक पहुंचने तक थ्रेड स्टैक आकार में बढ़ता रहता है।
स्टैक आकार (Xss और Xmso) विकल्पों को समायोजित करना ...
मेरा सुझाव है कि आप इस लिंक को देखें: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 StackOverflowError के कई संभावित कारण हैं, जैसा कि आप लिंक में देख सकते हैं ...।
मेरे मामले में मेरी दो गतिविधियाँ हैं। दूसरी गतिविधि में मैं ऑनक्रिएट विधि पर सुपर लगाना भूल गया।
super.onCreate(savedInstanceState);
StackOverflowError
, तो मैं यह नहीं कहता कि यह सवाल का जवाब दे रहा है। मुझे लगता है कि एक उचित उत्तर को या तो बहुत अधिक पुनरावृत्ति का उपयोग करने की तुलना में इस अपवाद को प्राप्त करने के लिए अन्य तरीकों को सूचीबद्ध करना चाहिए या यह कहें कि इस तरह के अपवाद को मैन्युअल रूप से फेंकने के अलावा कोई अन्य तरीका नहीं है।