Apa yang menyebabkan java.lang.StackOverflowError

Jawaban:

60

Periksa panggilan yang menyimpang untuk metode. Terutama disebabkan ketika ada panggilan rekursif untuk suatu metode. Contoh sederhananya adalah

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

    main.testMethod(1);
}

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

    System.out.println(i);
}

Di sini System.out.println (i); akan berulang kali didorong ke stack saat testMethod dipanggil.

Thota Srinath
sumber
1
Saya pikir Anda benar. Tapi apa solusinya. Karena kita sedang membuat metode recusing artinya kita membutuhkannya. Kami tidak ingin mengubah metode. Lalu bagaimana cara mengatasi kesalahan ini?
Ajay Sharma
1
atau Anda mengalami putaran tak terbatas!
yalematta
@yalematta, metode rekursif apa pun harus memiliki syarat untuk keluar. Jadi periksa apakah metode rekursif Anda diterapkan dengan benar dan selesai tergantung pada beberapa kondisi.
Ayaz Alifov
@AjaySharma Kami perlu merancang sistem kami agar sesuai dengan batas memori yang tersedia yang kami tetapkan ke JVM. Jika sistem berperilaku canggung dengan kesalahan berikut, maka kita perlu memeriksa basis kode kita.
Thota Srinath
22

Salah satu argumen (opsional) untuk JVM adalah ukuran tumpukan. Ini -Xss. Saya tidak tahu apa nilai defaultnya, tetapi jika jumlah total barang di tumpukan melebihi nilai itu, Anda akan mendapatkan kesalahan itu.

Umumnya, rekursi tak terbatas adalah penyebabnya, tetapi jika Anda melihatnya, pelacakan tumpukan Anda akan memiliki lebih dari 5 bingkai.

Coba tambahkan argumen -Xss (atau tingkatkan nilainya) untuk melihat apakah ini hilang.

nsayer
sumber
10

Apa yang sebenarnya menyebabkan java.lang.StackOverflowError biasanya merupakan rekursi yang tidak disengaja. Bagi saya, sering kali saya bermaksud memanggil metode super untuk metode terlarang. Seperti dalam kasus ini:

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

Pertama, sangat berguna untuk mengetahui apa yang terjadi di balik layar saat kita memanggil suatu fungsi. Argumen dan alamat tempat metode dipanggil didorong pada tumpukan (lihat http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ) sehingga metode yang dipanggil dapat mengakses argumen dan metode yang dipanggil selesai, eksekusi dapat dilanjutkan setelah panggilan. Tapi karena kita memanggil this.accelerate (acceleration, maxVelocity) secara rekursif (rekursi longgar saat metode memanggil dirinya sendiri. Untuk info lebih lanjut lihat http://en.wikipedia.org/wiki/Recursion_(computer_science)) kita berada dalam situasi yang dikenal sebagai rekursi tak terbatas dan kita terus menumpuk argumen dan alamat pengirim pada tumpukan panggilan. Karena tumpukan panggilan berukuran terbatas, kami akhirnya kehabisan ruang. Kehabisan ruang pada tumpukan panggilan dikenal sebagai luapan. Ini karena kami mencoba menggunakan lebih banyak ruang tumpukan daripada yang kami miliki dan data benar-benar meluap dari tumpukan. Dalam bahasa pemrograman Java, ini menghasilkan pengecualian runtime java.lang.StackOverflow dan akan segera menghentikan program.

Contoh di atas agak disederhanakan (meskipun itu terjadi pada saya lebih dari yang ingin saya akui.) Hal yang sama dapat terjadi secara lebih bulat tentang cara membuatnya sedikit lebih sulit untuk dilacak. Namun, secara umum, StackOverflow biasanya cukup mudah diatasi, setelah terjadi.

Secara teori, dimungkinkan juga untuk memiliki stack overflow tanpa rekursi, tetapi dalam praktiknya, ini tampaknya merupakan peristiwa yang cukup langka.

ptoinson.dll
sumber
8

apa yang java.lang.StackOverflowError

Kesalahan ditampilkan java.lang.StackOverflowErroruntuk menunjukkan bahwa tumpukan aplikasi telah habis, karena rekursi yang dalam, yaitu program / skrip Anda berulang terlalu dalam.

Detail

Kelas StackOverflowErrorextends VirtualMachineErroryang menunjukkan bahwa JVM telah atau telah kehabisan sumber daya dan tidak dapat beroperasi lebih lanjut. Kelas VirtualMachineErroryang meluas Errordigunakan untuk menunjukkan masalah serius yang tidak boleh ditangkap oleh aplikasi. Metode mungkin tidak mendeklarasikan kesalahan seperti itu dalam throwklausulnya karena kesalahan ini adalah kondisi abnormal yang tidak pernah diharapkan terjadi.

Sebuah contoh

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

}

Output Konsol

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)

Penjelasan

Saat panggilan fungsi dipanggil oleh Aplikasi Java, frame stack dialokasikan pada stack panggilan . The stack frameberisi parameter dari metode dipanggil, parameter lokal, dan alamat pengirim dari metode ini. Alamat pengirim menunjukkan titik eksekusi dari mana, eksekusi program harus dilanjutkan setelah metode yang dipanggil kembali. Jika tidak ada ruang untuk bingkai tumpukan baru, maka StackOverflowErrorakan dilempar oleh Java Virtual Machine (JVM).

Kasus paling umum yang mungkin dapat menghabiskan tumpukan aplikasi Java adalah rekursi. Dalam rekursi, metode memanggil dirinya sendiri selama eksekusinya. Recursionsalah satu teknik pemrograman tujuan umum yang paling kuat, tetapi harus digunakan dengan hati-hati, agar hal StackOverflowErroritu dihindari.

Referensi

DebanjanB
sumber
4

Saat panggilan fungsi dipanggil oleh aplikasi Java, frame stack dialokasikan pada stack panggilan. Bingkai tumpukan berisi parameter metode yang dipanggil, parameter lokalnya, dan alamat kembalian metode tersebut.

Alamat pengirim menunjukkan titik eksekusi dari mana, eksekusi program harus dilanjutkan setelah metode yang dipanggil kembali. Jika tidak ada ruang untuk bingkai tumpukan baru, StackOverflowError dilemparkan oleh Java Virtual Machine (JVM) .

Kasus paling umum yang mungkin dapat menghabiskan tumpukan aplikasi Java adalah rekursi.

Mohon dilihat

Bagaimana mengatasi StackOverflowError

IntelliJ Amiya
sumber
3

Solusi untuk pengguna Hibernate saat mengurai data:

Saya mengalami kesalahan ini karena saya sedang mengurai daftar objek yang dipetakan di kedua sisi @OneToManydan @ManyToOneke json menggunakan jackson yang menyebabkan pengulangan tak terbatas.

Jika Anda berada dalam situasi yang sama, Anda dapat menyelesaikannya dengan menggunakan anotasi @JsonManagedReferencedan @JsonBackReference.

Definisi dari API:

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

    Anotasi digunakan untuk menunjukkan bahwa properti beranotasi adalah bagian dari hubungan dua arah antar bidang; dan perannya adalah tautan "induk" (atau "penerusan"). Jenis nilai (kelas) properti harus memiliki satu properti kompatibel yang dianotasi dengan JsonBackReference. Tautan ditangani sedemikian rupa sehingga properti yang dianotasi dengan anotasi ini ditangani secara normal (berseri secara normal, tidak ada penanganan khusus untuk deserialisasi); itu adalah referensi pencocokan kembali yang memerlukan penanganan khusus

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

    Anotasi digunakan untuk menunjukkan bahwa properti terkait adalah bagian dari hubungan dua arah antar bidang; dan perannya adalah tautan "anak" (atau "kembali"). Jenis nilai properti harus berupa kacang: tidak dapat berupa Koleksi, Peta, Array, atau pencacahan. Tautan ditangani sedemikian rupa sehingga properti yang dianotasi dengan anotasi ini tidak berseri; dan selama deserialisasi, nilainya disetel ke instance yang memiliki tautan "terkelola" (meneruskan).

Contoh:

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;

Solusi lain adalah menggunakan @JsonIgnoreyang hanya akan menetapkan nol ke lapangan.

Emerica
sumber
2

Saya membuat program dengan hibernate, di mana saya membuat dua kelas POJO, keduanya dengan objek satu sama lain sebagai anggota data. Ketika dalam metode utama saya mencoba menyimpannya di database, saya juga mendapat kesalahan ini.

Hal ini terjadi karena kedua kelas saling merujuk, sehingga membuat perulangan yang menyebabkan kesalahan ini.

Jadi, periksa apakah ada jenis hubungan seperti itu dalam program Anda.

Singh
sumber
1

Pengecualian Stack Overflow dapat terjadi jika ukuran tumpukan benang terus bertambah hingga mencapai batas maksimum.

Menyesuaikan opsi Stack Sizes (Xss dan Xmso) ...

Saya sarankan Anda melihat tautan ini: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Ada banyak kemungkinan penyebab StackOverflowError, seperti yang Anda lihat di tautan ....

Marzieh Ghadirinia
sumber
Jawaban link saja umumnya tidak dapat diterima; tautan putus yang akan benar-benar membatalkan jawaban. Harap berikan beberapa konteks, kode, dan penjelasan jawabannya, bukan hanya tautan.
Jay
0

Dalam kasus saya, saya memiliki dua aktivitas. Pada aktivitas kedua saya lupa menempatkan super pada metode onCreate.

super.onCreate(savedInstanceState);
Julz Etnalob
sumber
Bahkan jika itu adalah cara yang mungkin untuk menaikkan a StackOverflowError, saya tidak berpikir itu menjawab pertanyaan. Saya pikir jawaban yang tepat harus mencantumkan cara lain untuk mendapatkan pengecualian ini daripada menggunakan terlalu banyak rekursi atau mengatakan bahwa pasti tidak ada cara lain untuk mendapatkan pengecualian seperti itu kecuali dengan melemparkannya secara manual.
JojOatXGME