Java çağrı yığınının maksimum derinliği nedir?


102

Bir StackOverflowError almadan önce çağrı yığınında ne kadar derine inmem gerekir? Cevap platformu bağımlı mı?



Bu iyi bir soru olduğu için başlığı, anlamla daha net bir şekilde ilişkili olduğunu düşündüğüm bir şeye güncelledim. (Önceden , örneğin, çalışma zamanında yakaladığınız belirli bir yığının derinliğine atıfta bulunduğunuzu düşünmüştüm ). Aynı fikirde değilseniz, tekrar değiştirmekten çekinmeyin.
Andrzej Doyle

Yanıtlar:



31

Sistemimde test ettim ve sabit bir değer bulamadım, bazen 8900 aramadan sonra yığın taşması oluyor, bazen sadece 7700 rastgele sayılardan sonra.

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
Bu, kuyruğun özyinelemeli olması ve hiç taşmaması gerekmiyor mu? Düzenleme: Üzgünüm. Java'da 8027'de çöktü; Scala'da ben sıkılmadan önce 8594755'e çıktı.
arya

9
@arya JVM semantiğinin önemli bir kısmı, kuyruk özyinelemesinin desteklenmemesidir. Bu, JVM'de kuyruk özyinelemeli dilleri uygulamak isteyenler için birçok ilginç sorun ortaya çıkarır.
Thorbjørn Ravn Andersen

2
public foo() { try { foo(); } finally { foo(); } }sadece java'da sonsuza kadar 'sanal olarak' çalışabilir.
Felype

benim için, StackOverflowError
8792'den

2
@ ThorbjørnRavnAndersen kuyruk özyineleme optimizasyonu desteklenmiyor. Daha doğrusu kuyruk özyinelemesine sahip olabilirsiniz. Çağrı yığınını büyütmemek için onu optimize etmez.
slim

19

Yığın boyutu ile ayarlanabilir -Xss komut satırı anahtarıyla ancak genel bir kural olarak, yeterince derin, binlerce olmasa da yüzlerce çağrı derinliğindedir. (Varsayılan, platforma bağlıdır, ancak çoğu platformda en az 256k'dir.)

Yığın taşması ile karşılaşırsanız,% 99 oranında koddaki bir hatadan kaynaklanır.


3
İkinci paragraf için +1. Bunu her zaman hatırlamak gerekir.
mcveat

6
Tutulmayı kullanarak yalnızca 1024 özyinelemeli çağrı alıyorum.
Norswap

2
@Norswap Bunu yığın izleme boyutuna göre mi belirliyorsunuz? Bu, yığının gerçek boyutuna bakılmaksızın 1024 ile sınırlı görünüyor.
Brian McCutchon

4

Bu iki çağrıyı karşılaştırın:
(1) Statik yöntem:

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) Farklı bir sınıf kullanan statik olmayan yöntem:

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

Test özyineleme sınıfı public int testRecursion(int number) {tek yöntemdir.

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.