[Solved] java.lang.StackOverflowError

java.lang.StackOverflowError is sub class of java.lang.VirtualMachineError. JVM throws a stack overflow when application stack exhausted, due to deep recursion.

What is StackOverFlowError?

When a method call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the java.lang.StackOverflowError is thrown by the Java Virtual Machine (JVM).

Reasons to occurs java.lang.StackOverFlowError

  • Recursion : A method invokes itself during it’s execution and method calling stack reach to max limit of JVMExample 1
  • Circular Dependency on method calling. Example 2

A method may not declare such errors in its throw clause, because these errors are abnormal conditions that shall never occur.

Constructors

  • StackOverflowError(): Constructs a StackOverflowError with no detail message.
  • StackOverflowError(String s): Constructs a StackOverflowError with the specified detail message.

Recusrsion StackOverFlowError Example

In this below recursion factorial of number example , I have commented out the recursion terminating condition to create StackOverFlowError.

package com.exceptions.errors;

public class StackOverFlowErrorExample {

	public static void main(String[] args) {
		RecursionExample recursion=new RecursionExample();
		System.out.println(recursion.fact(7));
	}
}

class RecursionExample
{
	public int fact(int n){
//Uncomment this condition to recursion terminating condition
//	    if( n == 0 ){
//	        return 1;
//	    }
	    return n * fact(n-1);
	}
}

Output

Exception in thread "main" java.lang.StackOverflowError
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at com.exceptions.errors.RecursionExample.fact(StackOverFlowErrorExample.java:18)
	at ......

Circular Dependency StackOverFlowError Example

In this example, we defined two classes, Company and Employee. The class Company contains one instance of the Employee class, while, the Employee class contains one instance of the Company class. Thus, we have a circular dependency between these two classes. Furthermore, each toString() method, invokes the corresponding toString() method of the other class, and so on, which results in a java.lang.StackOverflowError.

package com.exceptions.errors;

public class StackOverFlowExample2 {

	public static void main(String[] args) {
		Company company = new Company();
		System.out.println(company.toString());

	}
}

class Company {
	private int budget;
	private Employee employeeInstance = null;

	public Company() {
		budget = 0;
		employeeInstance = new Employee();
	}

	@Override
	public String toString() {
		return "FacingIssueOnIT : Company";
	}
}

class Employee {
	private int salary;
	private Company companyInstance = null;

	public Employee() {
		salary = 10;
		companyInstance = new Company();
	}

	@Override
	public String toString() {
		return "FacingIssueOnIT : Employee";
	}
}

Output

Exception in thread "main" java.lang.StackOverflowError
	at com.exceptions.errors.Employee.<init>(StackOverFlowExample2.java:33)
	at com.exceptions.errors.Company.<init>(StackOverFlowExample2.java:18)
	at com.exceptions.errors.Employee.<init>(StackOverFlowExample2.java:33)
	at com.exceptions.errors.Company.<init>(StackOverFlowExample2.java:18)
	at com.exceptions.errors.Employee.<init>(StackOverFlowExample2.java:33)
	at com.exceptions.errors.Company.<init>(StackOverFlowExample2.java:18)
	at com.exceptions.errors.Employee.<init>(StackOverFlowExample2.java:33)
	at com.exceptions.errors.Company.<init>(StackOverFlowExample2.java:18)
	at com.exceptions.errors.Employee.<init>(StackOverFlowExample2.java:33)
	at com.exceptions.errors.Company.<init>(StackOverFlowExample2.java:18)
	at com.exceptions.errors.Employee.<init>
....

How to deal with the StackOverflowError

  • In case of recursion, always apply terminating condition and that should execute in some cases so that method call not go to continuous call.
  • To inspect the stack trace and detect the repeating pattern of line numbers. These line numbers indicate the code being recursively called. Once you detect these lines, you must carefully inspect your code and understand why the recursion never terminates.
  • In case recursion and terminating condition are in place correctly.  You can increase the stack’s size, in order to allow a larger number of invocations. Default thread stack configuration depend on JVM some may equals to either 512KB, or 1MB. You can increase the thread stack size using the -Xss flag. This flag can be specified either via the project’s configuration, or via the command line. The format of the -Xss argument is:
     -Xss[g|G|m|M|k|K]

Know More

To know more about Java Exception Hierarchy, in-built exception , checked exception, unchecked exceptions and solutions. You can learn about Exception Handling in override methods and lots more. You can follow below links: