JAVA虚拟机java栈内存的问题!!

EricTao2 2017-09-11 08:39:52
最近在学习JVM,
学到java栈的部分,看到书上说栈溢出是因为给栈分配的内存不够。
我就在想,平时做算法问题的时候都是提倡用容器存储数据并且用循环求解(如果每次计算结果必须储存),而不用递归求解,说是递归可能导致栈溢出。但是其实用的都是线程栈的内存啊,递归多少次压了多少栈帧,换成是循环的话不也在容器里塞了多少数据吗。我知道我这样想法肯定是错的,请各位帮忙解答下QWQ!!
...全文
302 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
EricTao2 2017-09-12
  • 打赏
  • 举报
回复
引用 2 楼 u011619071 的回复:
你所说得 算法中如果有结果相同的计算要保存下来,这种方法叫备忘录,从算法的角度上来说确实更快。 因为相同的计算公式不需要重新计算一次、 从jvm级别的方法调用压栈的角度来说,少压了一些方法回调。jvm中的栈省了空间。 给你举个例子 .
method a(i){
  if(m)
       return n;
  return a(i-1) * a(i-2);
}
楼主不嫌麻烦可以把i=10的所有调用都写出来一次,就能体会到备忘录的好处,而jvm级别的压栈需要好好看看书中的内容。
你说的备忘录方法我理解,我也经常用就是不知道名字qwq。但是我思考的是,循环调用,把数据存在备忘录里和递归调用每次压栈往栈帧里存的数据大小是一样的啊,为何递归可能导致栈溢出(这里不考虑类似斐波那契数列这样可以节约计算次数的备忘录存储。我是看《剑指offer》很简单的一个算法,单链表倒置,每次的存储都不会影响到后面的计算,仅仅为了记录结果而已,书上却说递归可能栈溢出,推荐用循环,我就懵逼了)。
X元素 2017-09-12
  • 打赏
  • 举报
回复
你所说得 算法中如果有结果相同的计算要保存下来,这种方法叫备忘录,从算法的角度上来说确实更快。 因为相同的计算公式不需要重新计算一次、 从jvm级别的方法调用压栈的角度来说,少压了一些方法回调。jvm中的栈省了空间。 给你举个例子 .
method a(i){
  if(m)
       return n;
  return a(i-1) * a(i-2);
}
楼主不嫌麻烦可以把i=10的所有调用都写出来一次,就能体会到备忘录的好处,而jvm级别的压栈需要好好看看书中的内容。
EricTao2 2017-09-12
  • 打赏
  • 举报
回复
我明白了=-=,我是JVM没读明白,今天又看了下才发现。我之前以为在栈中声明的局部变量就一定一直存活是在栈中的,以为会占用栈帧内存导致线程栈溢出。后来才发现局部变量被赋给堆中的对象以后该销毁还是被销毁,所以大量的数据存在了堆中,栈内存不会溢出了。
fei1710 2017-09-12
  • 打赏
  • 举报
回复
方法调用需要额外的内存,比如返回地址,方法参数,CPU寄存器,方法里定义的变量
galiniur0u 2017-09-12
  • 打赏
  • 举报
回复
额。不知道楼主在纠结啥,递归只有在你的返回位置判断不正确的时候才会导致栈溢出,因为调用层级超过了正常值。递归是不会有问题的。难道说吃饭会噎死就不吃么。
X元素 2017-09-12
  • 打赏
  • 举报
回复
引用 3 楼 qq_37361576 的回复:
[quote=引用 2 楼 u011619071 的回复:] 你所说得 算法中如果有结果相同的计算要保存下来,这种方法叫备忘录,从算法的角度上来说确实更快。 因为相同的计算公式不需要重新计算一次、 从jvm级别的方法调用压栈的角度来说,少压了一些方法回调。jvm中的栈省了空间。 给你举个例子 .
method a(i){
  if(m)
       return n;
  return a(i-1) * a(i-2);
}
楼主不嫌麻烦可以把i=10的所有调用都写出来一次,就能体会到备忘录的好处,而jvm级别的压栈需要好好看看书中的内容。
你说的备忘录方法我理解,我也经常用就是不知道名字qwq。但是我思考的是,循环调用,把数据存在备忘录里和递归调用每次压栈往栈帧里存的数据大小是一样的啊,为何递归可能导致栈溢出(这里不考虑类似斐波那契数列这样可以节约计算次数的备忘录存储。我是看《剑指offer》很简单的一个算法,单链表倒置,每次的存储都不会影响到后面的计算,仅仅为了记录结果而已,书上却说递归可能栈溢出,推荐用循环,我就懵逼了)。[/quote] 我觉得你是没有明白,递归跟循环调用的区别是吧? java中的递归调用需要不断使用栈帧,计算次数一大,当然栈就报错了, 可不可以这样尝试理解一下, 循环依赖于执行结果,而递归依赖于调用。
EricTao2 2017-09-12
  • 打赏
  • 举报
回复
打错了,是单链表倒序输出,大神求指教
引用 2 楼 u011619071 的回复:
你所说得 算法中如果有结果相同的计算要保存下来,这种方法叫备忘录,从算法的角度上来说确实更快。 因为相同的计算公式不需要重新计算一次、 从jvm级别的方法调用压栈的角度来说,少压了一些方法回调。jvm中的栈省了空间。 给你举个例子 .
method a(i){
  if(m)
       return n;
  return a(i-1) * a(i-2);
}
楼主不嫌麻烦可以把i=10的所有调用都写出来一次,就能体会到备忘录的好处,而jvm级别的压栈需要好好看看书中的内容。
EricTao2 2017-09-11
  • 打赏
  • 举报
回复
在JVM内存的角度来说循环到底比递归好在哪呢

62,624

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧