简体   繁体   中英

StackOverflowError - Stack Size & Recursion

I thought it appropriate that my first question on Stack Overflow should be about a stack overflow error…

I solved “The Observed PIN” problem on Code Wars using a recursive algorithm:

https://www.codewars.com/kata/5263c6999e0f40dee200059d

import java.util.List;
import java.util.ArrayList;

public class ObservedPin {
  
  static StringBuilder sb = new StringBuilder();
  static int[] digits;
  static int[] index;
  static List<String> perms = new ArrayList<String>();
  static int[][] nums = {{0, 8}, {1, 2, 4}, {1, 2, 3, 5}, {2, 3, 6},
    {1, 4, 5, 7}, {2, 4, 5, 6, 8}, {3, 5, 6, 9}, {4, 7, 8},
    {5, 7, 8, 9, 0}, {6, 8, 9}};
    
    public static List<String> getPINs(String observed) {
      digits = new int[observed.length()];
      index = new int[observed.length()];
      for (int i = 0; i < digits.length; i++) {
        digits[i] = observed.charAt(i) - 48;
      } 
      permutations(0);
      return perms;
    }
    public static void permutations(int level) {
      if (index[level] == nums[digits[level]].length) {
        if (level == 0) {
          return;
        } else {
          index[level] = 0;
          index[level - 1]++;
          level = 0;
        }   
      } else {
        if (level == digits.length - 1) {
          //addPinToList(); **** commented out to see if this affected the required memory ****
          index[level]++;
        } else {
          level++;
        } 
      }
      permutations(level);  
    }
    public static void addPinToList() {
      for (int i = 0; i < digits.length; i++) {
        sb.append(Integer.toString(nums[digits[i]][index[i]])); 
      }
      perms.add(sb.toString());
      sb.setLength(0);
    }
}

After seeing other 'best practice' and 'clever' solutions, I realised this definitely wasn't the way to go, and I should have solved the problem a different way. Anyway, when testing my solution, I passed a PIN number with the highest possible number of permutations to the getPINs method. Any PIN comprising entirely fives & eights would result in 320,625 possible permutations. I used the PIN 58585858. When I ran the code, I got a StackOverflowError. I made some changes to the code that I thought might help but nothing worked. Eventually I increased the stack size and the code ran fine. Just out of interest, I commented out the line that adds the permutation to the 'perms' List, thinking this would also reduce the required memory, but when using the default 1Mb stack size, I got the same error. If a recursive method doesn't create any parameters or objects, or have any affect on the size of any existing parameters/objects, why does it take up so much memory? Is the JVM creating a new stack frame for every recursion, and so it's the frames that are using up the memory?

I'm teaching myself and I'm quite new to this, as you may have guessed.

Is the JVM creating a new stack frame for every recursion, and so it's the frames that are using up the memory?

Yes. A stack frame is what you need to be able to establish the context for execution (it is also known as an 'activation record') and to return. At an irreducible minimum, it contains a return address. In general it probably contains saved registers and routine arguments as well.

Link - stack frame description for JVM

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM