ความลึกสูงสุดของ java call stack คือเท่าไร?


102

ฉันต้องเข้าไปใน call stack ลึกแค่ไหนก่อนจะได้ StackOverflowError แพลตฟอร์มคำตอบขึ้นอยู่กับ?


1
เกี่ยวข้องกันอย่างใกล้ชิด: stackoverflow.com/questions/794227/…
finnw

เนื่องจากนี่เป็นคำถามที่ดีฉันจึงอัปเดตชื่อเรื่องเป็นสิ่งที่ฉันรู้สึกว่ามีความเกี่ยวข้องกับความหมายชัดเจนยิ่งขึ้น (ก่อนหน้านี้ฉันคิดว่าคุณอาจหมายถึงความลึกของสแต็กเฉพาะที่คุณบันทึกในรันไทม์เป็นต้น) อย่าลังเลที่จะเปลี่ยนกลับหากคุณไม่เห็นด้วย
Andrzej Doyle

คำตอบ:


62

ขึ้นอยู่กับจำนวนหน่วยความจำเสมือนที่จัดสรรให้กับสแต็ก

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

คุณสามารถปรับแต่งด้วย-Xssพารามิเตอร์ VM หรือด้วยตัวThread(ThreadGroup, Runnable, String, long)สร้าง


14
และบางทีขนาดของสแต็กเฟรมที่คุณวางไว้
duffymo

1
ขีด จำกัด ยังขึ้นอยู่กับการใช้งานสแต็กในฟังก์ชัน
Jarek Przygódzki

1
ถ้าเราไม่พูดถึง Xss ล่ะ?
a3.14_Infinity

31

ฉันทดสอบในระบบของฉันและไม่พบค่าคงที่บางครั้งสแต็กล้นเกิดขึ้นหลังจากการโทร 8900 ครั้งบางครั้งหลังจาก 7700 หมายเลขสุ่มเท่านั้น

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
ไม่ใช่กรณีที่หางเกิดซ้ำและไม่ควรล้น? แก้ไข: ขออภัย ใน Java มันพังที่ 8027; ใน Scala มันสูงถึง 8594755 ก่อนที่ฉันจะเบื่อ
arya

9
@arya ส่วนสำคัญของความหมาย JVM คือไม่รองรับการเรียกซ้ำหาง สิ่งนี้ให้ปัญหาที่น่าสนใจมากมายสำหรับผู้ที่ต้องการใช้ภาษาด้วยการเรียกซ้ำหางบน JVM
Thorbjørn Ravn Andersen

2
public foo() { try { foo(); } finally { foo(); } }สามารถเรียกใช้ 'เกือบ' ตลอดไปใน java เท่านั้น
Felype

สำหรับฉันStackOverflowErrorเกิดขึ้นหลังปี 8792
ericdemo07

2
ไม่รองรับการเพิ่มประสิทธิภาพการเรียกซ้ำหาง @ ThorbjørnRavnAndersen เห็นได้ชัดว่าคุณสามารถเรียกซ้ำหางได้ มันไม่ได้เพิ่มประสิทธิภาพเพื่อไม่ให้ call stack เติบโต
สลิม

19

ขนาดสแต็กสามารถตั้งค่าได้ด้วย-Xssสวิตช์บรรทัดคำสั่ง แต่ตามหลักทั่วไปแล้วมันลึกพอที่จะโทรได้ลึกหลายร้อยถ้าไม่ใช่หลายพันครั้ง (ค่าเริ่มต้นขึ้นอยู่กับแพลตฟอร์ม แต่อย่างน้อย 256k ในแพลตฟอร์มส่วนใหญ่)

หากคุณได้รับสแตกล้น 99% ของเวลาที่เกิดจากข้อผิดพลาดในโค้ด


3
+1 สำหรับย่อหน้าที่สอง หนึ่งควรจำไว้เสมอเกี่ยวกับเรื่องนี้
mcveat

6
เมื่อใช้ eclipse ฉันจะได้รับการโทรซ้ำ 1024 สายเท่านั้น
Norswap

2
@Norswap คุณกำลังกำหนดขนาดของการติดตามสแต็กหรือไม่? ซึ่งดูเหมือนจะ จำกัด ไว้ที่ 1024 โดยไม่คำนึงถึงขนาดจริงของสแต็ก
Brian McCutchon

4

เปรียบเทียบการเรียกทั้งสองนี้:
(1) วิธีการคงที่:

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) วิธีการไม่คงที่โดยใช้คลาสอื่น:

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

คลาสการทดสอบซ้ำมีpublic int testRecursion(int number) {วิธีเดียว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.