Java.lang.StackOverflowError hatası neden olur


Yanıtlar:


60

Yöntemler için tekrarlayıcı çağrıları kontrol edin. Esas olarak, bir yöntem için özyinelemeli çağrı olduğunda ortaya çıkar. Basit bir örnek

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

    main.testMethod(1);
}

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

    System.out.println(i);
}

Burada System.out.println (i); testMethod çağrıldığında art arda yığına itilecektir.


1
Bence haklısın. Ama bunun çözümü nedir? Çünkü biz bir yöntem yapıyoruz, buna ihtiyacımız var demektir. Yöntemde değişiklik yapmak istemiyoruz. Peki bu hatayı nasıl çözebiliriz?
Ajay Sharma

1
veya sonsuz bir döngüye giriyorsunuz!
yalematta

@yalematta, herhangi bir özyinelemeli yöntemin çıkmak için bir koşulu olmalıdır. Bu nedenle, yinelemeli yönteminizin doğru şekilde uygulanıp uygulanmadığını ve bazı koşullara bağlı olarak bitip bitmediğini kontrol edin.
Ayaz Alifov

@AjaySharma Sistemimizi JVM'ye atadığımız mevcut bellek sınırlarına uyacak şekilde tasarlamamız gerekiyor. Sistem aşağıdaki hatayla garip davranırsa, kod tabanımızı kontrol etmemiz gerekir.
Thota Srinath

22

JVM'nin (isteğe bağlı) argümanlarından biri yığın boyutudur. -Xss. Varsayılan değerin ne olduğunu bilmiyorum, ancak yığındaki toplam malzeme miktarı bu değeri aşarsa, bu hatayı alırsınız.

Genel olarak sonsuz özyineleme bunun nedenidir, ancak bunu görüyor olsaydınız, yığın izlemenizde 5'ten fazla kare olurdu.

Bunun gidip gitmediğini görmek için bir -Xss bağımsız değişkeni eklemeyi (veya birinin değerini artırmayı) deneyin.


10

Aslında java.lang.StackOverflowError hatası neden olan şey genellikle kasıtsız özyinelemedir. Benim için çoğu zaman, gizli yöntem için süper bir yöntem çağırmayı düşündüğüm zamandır. Bu durumda olduğu gibi:

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); 
    }
}

İlk olarak, bir işlevi çağırdığımızda perde arkasında ne olduğunu bilmek yararlıdır. Yöntemin çağrıldığı yerin argümanları ve adresi yığın üzerine itilir (bkz. Http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ), böylece çağrılan yöntem argümanlara erişebilir ve böylece çağrılan yöntem tamamlanır, çalıştırma çağrıdan sonra devam edebilir. Ancak bunu özyinelemeli olarak (ivme, maxVelocity) çağırdığımız için (bir yöntem kendisini çağırdığında özyineleme gevşek bir şekilde gerçekleşir. Daha fazla bilgi için bkz. Http://en.wikipedia.org/wiki/Recursion_(computer_science) ) sonsuz özyineleme olarak bilinen bir durumdayız ve yığınlamaya devam ediyoruz çağrı yığınındaki argümanlar ve dönüş adresi. Çağrı yığını boyut olarak sınırlı olduğundan, sonunda alanımız kalmaz. Çağrı yığınındaki alanın tükenmesi taşma olarak bilinir. Bunun nedeni, sahip olduğumuzdan daha fazla yığın alanı kullanmaya çalışmamız ve verilerin kelimenin tam anlamıyla yığını aşmasıdır. Java programlama dilinde, bu, java.lang.StackOverflow çalışma zamanı istisnasına neden olur ve programı hemen durdurur.

Yukarıdaki örnek biraz basitleştirilmiştir (benim başıma kabul etmek istediğimden daha fazla olmasına rağmen) Aynı şey, izini sürmeyi biraz daha zorlaştıracak şekilde daha kapsamlı bir şekilde gerçekleşebilir. Bununla birlikte, genel olarak, StackOverflow bir kez gerçekleştiğinde çözülmesi oldukça kolaydır.

Teoride, yineleme olmadan bir yığın taşması olması da mümkündür, ancak pratikte bu oldukça nadir bir olay gibi görünebilir.


8

Nedir java.lang.StackOverflowError

Hata java.lang.StackOverflowError, uygulama yığınının derin özyineleme nedeniyle tükendiğini belirtmek için atılır, yani programınız / betiğiniz çok derin yinelenir.

Detaylar

StackOverflowErrorUzanır VirtualMachineErrorJVM olmuştur veya kaynakların tükendi ve can daha da çalışmaz gösterir sınıfı. VirtualMachineErrorUzandığı Errorsınıf bir uygulama yakalamak gerektiğini bu ciddi sorunlara işaret etmek için kullanılır. Bir yöntem kendi throwcümlesinde bu tür hataları bildirmeyebilir, çünkü bu hatalar asla meydana gelmesi beklenmeyen anormal durumlardır.

Bir örnek

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);
    }

}

Konsol Çıkışı

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)

Açıklama

Bir Java Uygulaması tarafından bir işlev çağrısı çağrıldığında , çağrı yığınında bir yığın çerçevesi tahsis edilir . Çağrılan yöntemin, yerel parametreleri ve yöntemin dönüş adresinin parametreleri bulunuyor. Dönüş adresi, başlatılan yöntem döndükten sonra program yürütmesinin devam edeceği yürütme noktasını belirtir. Yeni bir yığın çerçevesi için yer yoksa, Java Sanal Makinesi (JVM) tarafından atılır.stack frameStackOverflowError

Bir Java uygulamasının yığınını tüketebilecek en yaygın durum özyinelemedir. Özyinelemede, bir yöntem yürütme sırasında kendisini çağırır. Recursionen güçlü genel amaçlı programlama tekniklerinden biridir, ancak StackOverflowErrorkaçınılması için dikkatli kullanılmalıdır .

Referanslar


4

Bir Java uygulaması tarafından bir işlev çağrısı çağrıldığında, çağrı yığınında bir yığın çerçevesi tahsis edilir. Yığın çerçevesi, çağrılan yöntemin parametrelerini, yerel parametrelerini ve yöntemin dönüş adresini içerir.

Dönüş adresi, başlatılan yöntem döndükten sonra program yürütmesinin devam edeceği yürütme noktasını belirtir. Yeni bir yığın çerçevesi için alan yoksa, StackOverflowError Java Sanal Makinesi (JVM) tarafından atılır .

Bir Java uygulamasının yığınını tüketebilecek en yaygın durum özyinelemedir.

Lütfen bir göz at

StackOverflowError nasıl çözülür?


3

Verileri ayrıştırırken Hazırda Bekletme kullanıcıları için çözüm:

Bu hatayı aldım çünkü her iki tarafa eşlenmiş nesnelerin bir listesini ayrıştırıyordum @OneToManyve@ManyToOne sonsuz bir döngüye neden olan jackson kullanarak json'u .

Eğer aynı durumda iseniz kullanarak bu çözebilir @JsonManagedReferenceve@JsonBackReference notları .

API'den Tanımlar:

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

    Ek açıklamalı özelliğin alanlar arasındaki iki yönlü bağlantının parçası olduğunu belirtmek için kullanılan ek açıklama; ve rolünün "ana" (veya "ileri") bağlantı olduğunu. Özelliğin değer türü (sınıfı), JsonBackReference ile açıklanmış tek bir uyumlu özelliğe sahip olmalıdır. Bağlantı, bu açıklama ile açıklanmış özellik normal olarak işlenecek şekilde işlenir (normal olarak serileştirilir, seriyi kaldırma için özel bir işlem yoktur); özel işlem gerektiren, eşleşen geri referanstır

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

    İlişkili özelliğin alanlar arasındaki iki yönlü bağlantının parçası olduğunu belirtmek için kullanılan ek açıklama; ve rolü "alt" (veya "geri") bağlantıdır. Özelliğin değer türü bir çekirdek olmalıdır: Koleksiyon, Harita, Dizi veya numaralandırma olamaz. Bağlantı, bu ek açıklama ile açıklama eklenen özellik serileştirilmeyecek şekilde işlenir; ve seriyi kaldırma sırasında, değeri "yönetilen" (ileri) bağlantıya sahip olan örneğe ayarlanır.

Misal:

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;

Başka bir çözüm, @JsonIgnoresadece alana null atan kullanmaktır.


2

Her ikisi de veri üyeleri olarak birbirinin nesnesiyle iki POJO sınıfı oluşturduğum hazırda bekletme ile bir program oluşturdum. Ana yöntemde onları veritabanına kaydetmeye çalıştığımda da bu hatayı aldım.

Bunun nedeni, her iki sınıfın da birbirine başvurması, dolayısıyla bu hataya neden olan bir döngü oluşturmasıdır.

Bu nedenle, programınızda bu tür bir ilişki olup olmadığını kontrol edin.


1

Yığın Taşması istisnaları, bir iş parçacığı yığınının boyutu maksimum sınıra ulaşana kadar büyümeye devam ettiğinde ortaya çıkabilir.

Yığın Boyutları (Xss ve Xmso) seçeneklerini ayarlama ...

Bu bağlantıyı görmenizi öneririm: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Bağlantıda görebileceğiniz gibi, StackOverflowError için birçok olası neden vardır ....


Yalnızca bağlantı yanıtları genellikle kabul edilemez; bağlantıların kopması, cevabı tamamen geçersiz kılar. Lütfen sadece bir bağlantı yerine biraz bağlam, kod ve cevabın açıklamasını sağlayın.
Jay

0

Benim durumumda iki faaliyetim var. İkinci aktivitede onCreate yöntemine süper koymayı unuttum.

super.onCreate(savedInstanceState);

A'yı yükseltmenin olası bir yolu olsa bile StackOverflowError, soruyu yanıtladığını sanmıyorum. Bence uygun bir cevap, bu istisnayı elde etmenin çok fazla özyineleme kullanmaktan başka yollarını listelemeli veya böyle bir istisnayı elde etmenin kesinlikle başka bir yolu olmadığını, elle atmaktan başka bir yol olmadığını söylemelidir.
JojOatXGME
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.