Вопрос рекурсии java try-catch-finally

public class Foo {

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

    public static void foo() {
        try {
            System.out.println("try");
            foo();
        } catch (Throwable e) {
            System.out.println("catch");
            foo();
        } finally {
                System.out.println("finally");
                foo();
        }
    }
}

кто может объяснить вывод этого кода?

1. вывод в режиме клиента eclipse (бесконечный):


    try
    try
    ....


    ...
    ...
    tryfinallyfinally
    tryfinallyfinally
    try
    try
    try
    tryfinallyfinally
    tryfinallyfinally
    try
    tryfinallyfinally
    tryfinallyfinally
    try
    ....
    ....

2. вывод на linux (сбой) в режиме сервера:


    try
    try
    ...

    ...
    try
    try
    try
    try
    try
    try
    MISSING EXCEPTION HANDLER for pc 0x00002aaaab1c53f0 and handler bci -1
       Exception:

     Compiled exception table :
    ExceptionHandlerTable (size = 3304 bytes)
    catch_pco = 700 (1 entries)
      bci -1 at scope depth 0 -> pco 11039
    catch_pco = 1736 (1 entries)
      bci -1 at scope depth 0 -> pco 11473
    catch_pco = 1756 (1 entries)
      bci -1 at scope depth 0 -> pco 11433
    catch_pco = 1776 (1 entries)


person qkpk    schedule 19.07.2011    source источник
comment
кто может объяснить вывод этого кода?: Может быть, вы. Что вы получили, когда запустили это?   -  person Harry Joy    schedule 19.07.2011
comment
... переполнение стека   -  person MarcoS    schedule 19.07.2011
comment
Вывод действительно неожиданный: попробуйте попробуйте попробуйте попробуйте наконец, наконец, попробуйте, наконец,   -  person Sergey Aslanov    schedule 19.07.2011
comment
Чего вы ожидали? Ничего разумного я бы не ждал. Вы ловите StackOverflowError, а затем сразу же переходите к вызову другого метода (того, который сам вызовет довольно много методов).   -  person Dunes    schedule 19.07.2011
comment
Можете ли вы объяснить, чего вы надеетесь достичь, делая это? то есть есть ли смысл?   -  person Peter Lawrey    schedule 19.07.2011
comment
некоторые новые строки не печатаются, потому что стек переполняется где-то после write(s) и до вызова newLine() в PrintStream.   -  person ZhongYu    schedule 01.09.2015


Ответы (1)


Кажется, я помню это из книги "Java Puzzlers". Блок try выполняет неограниченную рекурсию, которая быстро приводит к возникновению ошибки StackOverflowError. Блоки try и catch возобновляют рекурсию, но с соответственно меньшим оставшимся стеком. Однако оставшийся стек снова увеличивается по мере возврата каждого рекурсивного вызова...

Конечным результатом является граф вызовов, образующий дерево, глубина которого зависит от размера стека; с размером стека по умолчанию для основных JVM дерево становится настолько большим, что вам придется ждать много, много миллиардов лет, чтобы оно было полностью пройдено и программа завершилась.

Изменить: это то, что вы видите в режиме клиента: обход графа вызовов. То, что вы видите в Linux в режиме сервера, является либо ошибкой JVM, либо недостатком оборудования (неисправная оперативная память может иметь такой эффект).

person Michael Borgwardt    schedule 19.07.2011
comment
Я предполагаю, что это была ошибка в JIT в Linux. - person David Conrad; 12.07.2012