Solution:
Your algorithm is exquisite. But int
is too small for your computations, it fails for this input:
printSyra(113383, 1);
At some point integer swamps to negative value and your execution goes instance, recursing infinitely. Alter int num
to long num
and you'll be exquisite - for some time. Afterwards you'll require BigInteger
.
The longest advancement for any primary starting number less than 100 million is 63,728,127, which has 949 steps. For begining numbers less than 1 billion it is 670,617,279, with 986 steps, and for numbers less than 10 billion it is 9,780,657,630, with 1132 steps.
The complete number of steps is identical to maximum nesting level (stack depth) you can anticipate. So even for relatively big numbers StackOverflowError
should not occur. Have a look at this execution employing BigInteger
:
private static int printSyra(BigInteger num, int count) {
if (num.equals(BigInteger.ONE)) {
return count;
}
if (num.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
return printSyra(num.divide(BigInteger.valueOf(2)), count + 1);
} else {
return printSyra(num.multiply(BigInteger.valueOf(3)).add(BigInteger.ONE), count + 1);
}
}
It performs even for very big values:
printSyra(new BigInteger("9780657630"), 0) //1132
printSyra(new BigInteger("104899295810901231"), 0) //2254
The easiest solution is to carefully inspect the stack trace and detect the repeating pattern of line numbers. These line numbers imply the code that is being recursively named. At one time you detect these lines, look for the terminating condition (base condition) for the recursive calls.
At one time you have verified that the recursion is executed exactly, you can rise the stack’s size in order to approve a larger number of invocations. The stack size can be increased by altering the settings of your compiler.
What is StackOverFlowError?
At the time a method call is called by a Java application, a stack frame is situated 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 explains the execution point from which, the program execution shall continue after the invoked method returns. In case there is no space for a new stack frame then, the java.lang.StackOverflowError is thrown by the Java Virtual Machine (JVM).
Causes to happens java.lang.StackOverFlowError
- Recursion : A method calls itself at the time it’s execution and method calling stack reach to max limit of JVM. Example 1
- Circular Dependency on method calling. Example 2
A method may not declare such errors in its throw clause, since these errors are abnormal conditions that shall never happen.
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 under 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);
}
}
Circular Dependency StackOverFlowError Example
In this example, we defined two classes, Company and Employee. The class Company holds one instance of the Employee class, while, the Employee class holds one instance of the Company class. In this way, we have a circular dependency between these two classes. Besides, every toString() method, invite the similar 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";
}
}
How to deal with the StackOverflowError
- In case of recursion, always apply terminating condition and that should fulfill in some cases so that method call not go to successive call.
- To reconnoiter the stack trace and detect the repeating pattern of line numbers. These line numbers show the code being recursively called. At one time you detect these lines, you should gingerly inspect your code and understand why the recursion never terminates.
- In case recursion and terminating state are in position exactly. You can raise the stack’s size, in order to approve a larger number of invitation. Default thread stack configuration rely on JVM few may equals to either 512KB, or 1MB. You can raise the thread stack size emplying the -Xss flag. This flag can be seclude either through the project’s configuration, or through the command line. The format of the -Xss argument is:
-Xss[g|G|m|M|k|K]