Độ sâu tối đa của ngăn xếp cuộc gọi java là bao nhiêu?


100

Tôi cần đi sâu bao nhiêu vào ngăn xếp cuộc gọi trước khi gặp lỗi StackOverflowError? Nền tảng câu trả lời có phụ thuộc không?


1
Liên quan chặt chẽ: stackoverflow.com/questions/794227/...
finnw

Vì đây là một câu hỏi hay, nên tôi đã cập nhật tiêu đề thành một thứ mà tôi cảm thấy có liên quan rõ ràng hơn với ý nghĩa. (Trước đây, tôi nghĩ rằng bạn có thể đang đề cập đến độ sâu của một ngăn xếp cụ thể mà bạn đã chụp trong thời gian chạy chẳng hạn). Vui lòng đổi lại nếu bạn không đồng ý.
Andrzej Doyle,

Câu trả lời:


60

Nó phụ thuộc vào số lượng bộ nhớ ảo được phân bổ cho ngăn xếp.

http://www.odi.ch/weblog/posting.php?posting=411

Bạn có thể điều chỉnh điều này bằng -Xsstham số VM hoặc với hàm Thread(ThreadGroup, Runnable, String, long)tạo.


13
Và có lẽ kích thước của khung xếp chồng bạn đang đặt trên đó?
duffymo

1
Giới hạn cũng phụ thuộc vào việc sử dụng ngăn xếp trong hàm.
Jarek Przygódzki

1
nếu chúng ta không đề cập đến Xss, sau đó?
a3.14_Infinity

31

Tôi đã thử nghiệm trên hệ thống của mình và không tìm thấy bất kỳ giá trị không đổi nào, đôi khi tràn ngăn xếp xảy ra sau 8900 cuộc gọi, đôi khi chỉ sau 7700, các số ngẫu nhiên.

public class MainClass {

    private static long depth=0L;

    public static void main(String[] args){
        deep(); 
    }

    private static void deep(){
        System.err.println(++depth);
        deep();
    }

}

15
Có phải đây là trường hợp đệ quy đuôi và không bao giờ bị tràn? Chỉnh sửa: Xin lỗi. Trong Java, nó gặp sự cố lúc 8027; trong Scala, nó đã lên đến 8594755 trước khi tôi cảm thấy nhàm chán.
arya

9
@arya một phần quan trọng của ngữ nghĩa JVM là đệ quy đuôi không được hỗ trợ. Điều này đưa ra rất nhiều vấn đề thú vị cho những ai muốn triển khai các ngôn ngữ có đệ quy đuôi trên JVM.
Thorbjørn Ravn Andersen

2
public foo() { try { foo(); } finally { foo(); } }có thể chạy 'ảo' mãi mãi, chỉ trong java.
Felype

đối với tôi, StackOverflowErrorxảy ra sau khi sau 8792
ericdemo07

2
@ ThorbjørnRavnAndersen tối ưu hóa đệ quy đuôi không được hỗ trợ. Rõ ràng là bạn có thể có đệ quy đuôi. Nó chỉ không tối ưu hóa nó để không phát triển ngăn xếp cuộc gọi.
slim

19

Kích thước ngăn xếp có thể được đặt bằng công -Xsstắc dòng lệnh nhưng theo quy luật chung, nó đủ sâu, hàng trăm nếu không muốn nói là hàng nghìn lệnh. (Mặc định là phụ thuộc vào nền tảng, nhưng ít nhất là 256k trong hầu hết các nền tảng.)

Nếu bạn gặp sự cố tràn ngăn xếp, thì 99% trường hợp là do lỗi trong mã.


3
+1 cho đoạn thứ hai. Người ta nên luôn nhớ về điều đó.
mcveat

6
Sử dụng eclipse, tôi chỉ nhận được 1024 cuộc gọi đệ quy.
Norswap

2
@Norswap Bạn có đang xác định điều đó bằng kích thước của dấu vết ngăn xếp không? Điều đó dường như được giới hạn ở 1024 bất kể kích thước thực tế của ngăn xếp.
Brian McCutchon

4

So sánh hai lệnh gọi này:
(1) Phương thức tĩnh:

public static void main(String[] args) {
    int i = 14400; 
    while(true){   
        int myResult = testRecursion(i);
        System.out.println(myResult);
        i++;
    }
}

public static int testRecursion(int number) {
    if (number == 1) {
        return 1;
    } else {
        int result = 1 + testRecursion(number - 1);
        return result;
    }    
}
 //Exception in thread "main" java.lang.StackOverflowError after 62844

(2) Phương thức không tĩnh sử dụng một lớp khác:

public static void main(String[] args) {
    int i = 14400;
    while(true){       
        TestRecursion tr = new TestRecursion ();
        int myResult = tr.testRecursion(i);
        System.out.println(myResult);
        i++;
    }
} 
//Exception in thread "main" java.lang.StackOverflowError after 14002

Kiểm tra lớp đệ quy public int testRecursion(int number) {là phương thức duy nhất.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.