Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

syntax - Java Riddle with finally block and recursion

I just prepared a game for our team about java riddles. So to say, small pieces of java code that do things that you do not expect at the first glance.

While googeling for such riddles I also scribbled around in my IDE and tried out some weird things that you would never write in production code. Just for the fun of it.

Suddenly I came up with the following:

public static int cnt = 0;
public static int blubb() {
    try {
        cnt++;
        return blubb();
    } finally {
        return cnt;
    }
}

public static void main(String[] args) {
    System.out.println(cnt + ": " + Main.blubb() + ": " + cnt);
}

When executed it prints something like "0: 21245: 21245" where 21245 is different for each run.

I'd expect either an endless recursion, or returning 1 in the finally block (0: 1: 1)

When adding a catch block to catch Throwable and debugging, the debugger will never stop in this block.

Can somebody explain me what is going on here?

question from:https://stackoverflow.com/questions/65899376/java-riddle-with-finally-block-and-recursion

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Adding a catch block like this, and not seeing a stack trace, doesn't indicate that nothing was thrown:

    } catch (Throwable t) {
      t.printStackTrace();
      throw t;
    } finally { ... }

Not being able to print the stack trace of a StackOverflowError immediately after catching a StackOverflowError is expected: a SOE literally means that no more method calls can be made.

But to invoke printStackTrace(), you need to make another method call. So, that method call actually results in another, separate StackOverflowError, which you don't attempt to print. But then the return in the finally causes the StackOverflowError to be discarded.

Try this, which doesn't require a method invocation when the StackOverflowError is thrown:

import java.util.*;

class Main {
  public static int cnt = 0;

  private static Throwable caught;

  public static int blubb() throws Throwable {
    try {
      cnt++;
      return blubb();
    } catch (Throwable t) {
      caught = t;
      throw t;
    } finally {
      return cnt;
    }
  }

  public static void main(String[] args) throws Throwable {
    System.out.println(cnt + ": " + Main.blubb() + ": " + cnt);
    System.out.println(caught);
  }
}

For me, this prints:

0: 9672: 9672
java.lang.StackOverflowError

So yes, a StackOverflowError was caught.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...