Câu hỏi Nguyên nhân gây ra một java.lang.StackOverflowError


Điều gì có thể gây ra java.lang.StackOverflowError? Các bản in ngăn xếp mà tôi nhận được không phải là rất sâu ở tất cả (chỉ có 5 phương pháp).


76
2017-07-07 18:26


gốc


Bài đăng này có thể giúp: stackoverflow.com/questions/860550/… - Jake Greene


Các câu trả lời:


Kiểm tra cho bất kỳ cuộc gọi recusive cho phương pháp. Chủ yếu là nó được gây ra khi có cuộc gọi đệ quy cho một phương pháp. Một ví dụ đơn giản là

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

    main.testMethod(1);
}

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

    System.out.println(i);
}

Ở đây System.out.println (i); sẽ được đẩy nhiều lần để ngăn xếp khi testMethod được gọi.


57
2017-07-08 10:01



Tôi nghĩ bạn đúng. Nhưng giải pháp của nó là gì. Bởi vì chúng tôi đang thực hiện một phương pháp recusing nó có nghĩa là chúng ta cần điều đó. Chúng tôi không muốn thay đổi phương thức. Vậy làm cách nào để phân loại lỗi này? - Ajay Sharma
hoặc bạn đang đi vào một vòng lặp vô hạn! - yalematta
@yalematta, bất kỳ phương pháp đệ quy nào cũng phải có điều kiện để thoát. Vì vậy, kiểm tra xem phương pháp đệ quy của bạn được thực hiện đúng và kết thúc tùy thuộc vào một số điều kiện. - Sa Qada
@AjaySharma Chúng tôi cần thiết kế hệ thống của mình để phù hợp với ranh giới bộ nhớ có sẵn mà chúng tôi đã gán cho JVM. Nếu hệ thống hoạt động khó xử với lỗi sau thì chúng ta cần phải kiểm tra cơ sở mã của chúng tôi. - Thota Srinath


Một trong các đối số (tùy chọn) cho JVM là kích thước ngăn xếp. Đó là -Xss. Tôi không biết giá trị mặc định là gì, nhưng nếu tổng số lượng nội dung trên ngăn xếp vượt quá giá trị đó, bạn sẽ nhận được lỗi đó.

Nói chung, đệ quy vô hạn là nguyên nhân của việc này, nhưng nếu bạn thấy điều đó, dấu vết ngăn xếp của bạn sẽ có nhiều hơn 5 khung hình.

Hãy thử thêm đối số -Xss (hoặc tăng giá trị của một đối số) để xem liệu điều này có biến mất hay không.


19
2017-07-07 18:29





Cái thực sự gây ra một java.lang.StackOverflowError thường là đệ quy không chủ ý. Đối với tôi, thường là khi tôi dự định gọi một phương pháp siêu cho phương pháp bị bỏ qua. Chẳng hạn như trong trường hợp này:

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

Đầu tiên, nó rất hữu ích để biết những gì xảy ra đằng sau hậu trường khi chúng ta gọi một hàm. Các đối số và địa chỉ của nơi mà phương thức được gọi được đẩy lên ngăn xếp (xem http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management) để phương thức được gọi có thể truy cập các đối số và do đó khi phương thức được gọi hoàn thành, thực thi có thể tiếp tục sau cuộc gọi. Nhưng kể từ khi chúng tôi đang gọi this.accelerate (tăng tốc, maxVelocity) đệ quy (đệ quy là lỏng lẻo khi một phương pháp gọi chính nó. Để biết thêm thông tin xem http://en.wikipedia.org/wiki/Recursion_(computer_science)) chúng tôi đang ở trong một tình huống được gọi là đệ quy vô hạn và chúng tôi tiếp tục xếp chồng các đối số và trả lại địa chỉ trên ngăn xếp cuộc gọi. Kể từ khi ngăn xếp cuộc gọi là hữu hạn về kích thước, chúng tôi cuối cùng đã hết dung lượng. Việc hết dung lượng trên ngăn xếp cuộc gọi được gọi là tràn. Điều này là bởi vì chúng tôi đang cố gắng sử dụng nhiều không gian ngăn xếp hơn chúng tôi có và dữ liệu theo nghĩa đen sẽ tràn ngăn xếp. Trong ngôn ngữ lập trình Java, điều này dẫn đến ngoại lệ thời gian chạy java.lang.StackOverflow và ngay lập tức sẽ tạm dừng chương trình.

Ví dụ trên là hơi đơn giản (mặc dù nó xảy ra với tôi nhiều hơn tôi muốn thừa nhận.) Điều tương tự có thể xảy ra trong một vòng nhiều hơn về cách làm cho nó một chút khó khăn hơn để theo dõi. Tuy nhiên, nói chung, StackOverflow thường khá dễ giải quyết, một khi nó xảy ra.

Về lý thuyết, nó cũng có thể có một tràn ngăn xếp mà không đệ quy, nhưng trong thực tế, nó sẽ xuất hiện là một sự kiện khá hiếm.


9
2018-06-20 03:35





Khi một cuộc gọi hàm được gọi bởi một ứng dụng Java, một khung ngăn xếp được cấp phát trên ngăn xếp cuộc gọi. Khung stack chứa các tham số của phương thức được gọi, các tham số cục bộ của nó và địa chỉ trả về của phương thức.

Địa chỉ trả về biểu thị điểm thực thi từ đó, việc thực hiện chương trình sẽ tiếp tục sau khi phương thức được gọi trả về. Nếu không có khoảng trống cho khung chồng mới thì StackOverflowError được ném bởi Máy ảo Java (JVM).

Trường hợp phổ biến nhất có thể làm cạn kiệt ngăn xếp của ứng dụng Java là đệ quy.

Xin vui lòng có một cái nhìn

Cách giải quyết StackOverflowError


4
2017-09-28 12:05





Những gì là java.lang.StackOverflowError

Lỗi java.lang.StackOverflowError được ném ra để cho biết rằng ngăn xếp của ứng dụng đã cạn, do đệ quy sâu, tức là chương trình / tập lệnh của bạn đệ quy quá sâu.

Chi tiết

Các StackOverflowError kéo dài VirtualMachineError lớp chỉ ra rằng JVM đã hoặc đã hết nguồn lực và không thể hoạt động thêm. Các VirtualMachineError mở rộng Error lớp được sử dụng để chỉ ra những vấn đề nghiêm trọng mà một ứng dụng không nên bắt. Một phương pháp có thể không khai báo các lỗi đó trong throw vì các lỗi này là những điều kiện bất thường mà không bao giờ được mong đợi xảy ra.

Một ví dụ

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

}

Đầu ra Console

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)

Giải thích

Khi một cuộc gọi hàm được gọi bởi một ứng dụng Java, một chồng khung được phân bổ trên ngăn xếp cuộc gọi. Các stack frame chứa các tham số của phương thức được gọi, các tham số cục bộ của nó và địa chỉ trả về của phương thức. Địa chỉ trả về biểu thị điểm thực thi từ đó, việc thực hiện chương trình sẽ tiếp tục sau khi phương thức được gọi trả về. Nếu không có khoảng trống cho khung chồng mới thì StackOverflowError được ném bởi Máy ảo Java (JVM).

Trường hợp phổ biến nhất có thể làm cạn kiệt ngăn xếp của ứng dụng Java là đệ quy. Trong đệ quy, một phương thức tự gọi nó trong quá trình thực hiện nó. Recursion một trong những kỹ thuật lập trình đa năng mạnh mẽ nhất, nhưng phải được sử dụng cẩn thận, để cho StackOverflowError để tránh.

Tài liệu tham khảo


4
2017-12-15 11:29





Tôi tạo ra một chương trình với hibernate, trong đó tôi tạo ra hai lớp POJO, cả hai với một đối tượng của nhau như các thành viên dữ liệu. Khi trong phương pháp chính tôi đã cố gắng để lưu chúng trong cơ sở dữ liệu tôi cũng có lỗi này.

Điều này xảy ra bởi vì cả hai lớp đều tham chiếu lẫn nhau, do đó tạo ra một vòng lặp gây ra lỗi này.

Vì vậy, kiểm tra xem có bất kỳ loại mối quan hệ như vậy tồn tại trong chương trình của bạn hay không.


2
2018-04-03 18:40





Các trường hợp ngoại lệ tràn ngăn xếp có thể xảy ra khi ngăn xếp luồng tiếp tục tăng kích thước cho đến khi đạt đến giới hạn tối đa.

Điều chỉnh tùy chọn Kích thước ngăn xếp (Xss và Xmso) ...

Tôi đề nghị bạn thấy liên kết này: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Có nhiều nguyên nhân có thể xảy ra với StackOverflowError, như bạn có thể thấy trong liên kết ....


1
2017-09-02 12:05



Liên kết chỉ câu trả lời thường không được chấp nhận; liên kết phá vỡ mà hoàn toàn sẽ làm mất hiệu lực câu trả lời. Vui lòng cung cấp một số ngữ cảnh, mã và giải thích câu trả lời thay vì chỉ một liên kết. - Jay
Mặc dù liên kết này có thể trả lời câu hỏi, nhưng tốt hơn nên đưa các phần quan trọng của câu trả lời vào đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. - - Từ đánh giá - Mark Rotteveel