递归会导致Java或Java IDE崩溃吗?递归求素数遇StackOverflowError
递归导致的StackOverflowError问题解析
嘿,你遇到的这个java.lang.StackOverflowError本质原因很明确:递归调用的层数太深,耗尽了Java线程的栈内存。
具体成因
Java里每个线程都有一块固定大小的调用栈(默认大小通常在几百KB到几MB之间,由JVM配置决定)。每次调用recursion()方法时,JVM都会在栈中创建一个新的「栈帧」,用来存储方法的参数、局部变量和返回地址。
你的代码逻辑是:每检查一个数字(不管是不是素数),都会递归调用一次recursion()。从12开始到4330左右,已经产生了四千多次连续的递归调用——每一次调用都占着栈空间,当栈帧的总数超过JVM允许的上限时,自然就抛出栈溢出错误了。
你说能运行到4330但没法更大,就是因为到这个数值时,栈空间刚好被耗尽。这和IDE(Eclipse Neon)没啥关系,是Java虚拟机的栈内存限制导致的。
解决方案:用迭代替代递归
递归虽然写法简洁,但这种需要连续调用几千次的场景,完全不适合用递归——换成循环(迭代)就能彻底解决问题,因为迭代不会不断创建新的栈帧,而是在同一个栈帧里重复执行逻辑。
修改后的代码示例:
import java.util.ArrayList; public class LargePrimeNumber { static ArrayList<Integer> PrimeDataBase = new ArrayList<>(); static int cd = 12; public static void main(String[] args) { PrimeDataBase.add(2); PrimeDataBase.add(3); PrimeDataBase.add(5); PrimeDataBase.add(7); PrimeDataBase.add(11); // 用while循环替代递归逻辑 while (cd < 5000) { boolean prime = true; // 优化:只检查到cd的平方根,减少循环次数 int sqrtCd = (int) Math.sqrt(cd); for (int i = 0; i < PrimeDataBase.size(); i++) { int primeNum = PrimeDataBase.get(i); if (primeNum > sqrtCd) { break; } if (cd % primeNum == 0) { prime = false; break; } } if (prime) { PrimeDataBase.add(cd); System.out.println(cd + " is prime"); } cd++; } } }
额外提个小优化:检查素数时,不需要遍历所有已有的素数,只需要检查到cd的平方根就够了——因为如果一个数有大于其平方根的因数,必然对应一个小于平方根的因数,这样能大幅减少循环次数,提升程序效率。
内容的提问来源于stack exchange,提问作者Kenneth
相关产品推荐
相关产品推荐

