Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Main Recursively

Tags:

java

recursion

public class Demo
{
    static int i=0;
    public static void main(String args[])
    {
        System.out.println("Hello"+(i++));
        main(args);
    }
}

In this program I am calling main with instance variable.

It runs properly upto some point but after some Hello prints it gives StackOverFlow Exception.

So i put int to find how many times it gets printed.

I run this program it gives Exception after i=4158.

But I run it several times it gives Exception at different value of i like 4155,4124,4154 etc.

As I know here StackOverFlow is generated because of bad or Unconditional recursive call.

I tried to figure out it but don't know what's exactly happening.

I want to know why after 4158 (or other values) ?

Is it dependent on my System or is it dependent on My Program?

like image 360
akash Avatar asked Mar 26 '26 13:03

akash


1 Answers

First, you're shadowing your args variable. The args defined in your field isn't going to be regarded as the same args you're attempting to recursively call in main.

Second, the recursion eventually runs out, but that's dependent on how much memory you have allocated for the application, and what else is in memory at the time. If you gave it something like 2GB (or more) of space to work with, the recursion would still run out - but likely at a higher value.

As a for-instance, this is what I get when I run with -Xmx6G:

10791
10796
10789

The number is likely different due to what else my OS is running.

Now, for the reason it runs out: your calls are placed on a stack, which is not a finite place in memory; it can (and sometimes does) run out.

Every time you call a function in Java, it goes onto the stack.

First time through:
 > main(0)

main() is always called, so it's always on the bottom of the stack.

If we were to call main() again, then another call of it gets placed on the stack:

Second time through:
 > main(1)
 > main(0)

For most simple applications, only a handful of calls (under 100) are ever put onto the call stack, and their lifecycle is short enough that they don't last on the call stack very long.

However, your application is different, since it's lacking something known as the base case. This is what you use to decide to stop recursing.

Take, for example, the famous factorial function, which states:

      { 1          if n = 0
n! = <
      { n * (n-1)! if n > 0

We have our base case: If n = 0, then we don't continue to recurse any further. Otherwise, we just keep on goin'.

Here's what that looks like in code:

public long factorial(int n) {
    return n == 0 ? 1L : n * factorial(n-1);
}

Once I've reached my base case, then I stop adding calls to the stack - I actually begin resolving them.

Here's a sample of what factorial(4) looks like:

> factorial(4)
  > factorial(3)
    > factorial(2)
      > factorial(1)
        > factorial(0)
        > 1
      > 1 * 1
    > 1 * 1 * 2
  > 1 * 1 * 2 * 3
> 1 * 1 * 2 * 3 * 4

So, this is all to say: if you're going to do a recursive function, make sure that the recursion can end. Otherwise, you'll be running into this issue all the time.

like image 114
Makoto Avatar answered Mar 29 '26 03:03

Makoto