Ошибка StackOverflow, Java - PullRequest
0 голосов
/ 23 мая 2018

Почему я получаю странный вывод в случае StackOverflowError?

public class Hello{  
    public static void main(String args[]){  
        System.out.println(new Exception().getStackTrace().length);  
        m1();  
    }  
    public static void m1(){  
        m2();  
    }  
    public static void m2(){  
        try{  
            m1();  
        }catch(StackOverflowError err){  
            System.out.println(err.getStackTrace().length);  
        }  
    }  
}  

Output (a)-
        1
        102410241024102410241024102410241024

Output (b) -
        1024

Output (c)-
        1
        1024   

При выполнении вышеуказанного кода я получаю Output (a). Но когда я комментирую первую строкуМетод main Я получаю Output (b).

Я должен получать Output (c), когда выполняю приведенный выше код, оставляя первую строку в методе main без комментария

Почему 1024 получаетнапечатано так много раз в Output (a)?

Я пытался выяснить размер стека по умолчанию, подняв StackOverflowError и преднамеренно его перехватив. Я напечатал размер стека перед вызовом метода m1 из основного метода.

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Прежде всего, обратите внимание, что не имеет значения, что вы печатаете для того, чтобы такое поведение происходило, достаточно любого отпечатка.

С отпечатком в начале: итак, с некоторой отладкой я заметилчто в методе PrintStream.write(String s) есть строка textOut.flushBuffer(), которая неожиданно завершается с ошибкой.Результатом этого, по сути, является то, что запрошенная строка добавляется в буфер, но буфер не сбрасывается, а новая строка не добавляется в буфер, потому что это отдельный шаг, и он идет намного позже точки вызовачто не удалось.Затем в конце, при последней печати, этот метод завершается успешно, поэтому ваша строка выводится на консоль вместе со всеми предыдущими, поскольку они ожидали в буфере (1024 раза).

Без печати в начале: программа даже не достигает уровня textOut.flushBuffer() при всех попытках печати, она даже не достигает самого метода println.Это, вероятно, потому что он должен инициализировать некоторые классы по пути, так как это не было сделано раньше (как с печатью в начале) и не может, потому что стек переполнен.Таким образом, в отличие от предыдущего случая с печатью в начале, в буфер ничего не добавляется, поэтому в конце мы напечатали только одну строку (1024, 1 раз).

Я понятия не имею, если этоимеет какой-то смысл, но это было, конечно, весело.

0 голосов
/ 24 мая 2018

Предположим, у вас в стеке

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 

, а затем переполнение стека, затем ошибка обнаруживается в этом стеке:

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2

, а затем выдается другая ошибка, потому что вы вызываетеметод в вашем предложении catch, а затем вы ловите с этим стеком:

m1 - > m2 - > m1 - > m2 - > m1 - > m2

, затем выдается другая ошибка и так далее.Это будет продолжаться до тех пор, пока ваше предложение catch больше не вызовет другую ошибку.Также обратите внимание, что когда и как вы получите ошибку, зависит от того, когда и как ваши методы компилируются JIT, что непредсказуемо.

...