A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© wangning9130 中级黑马   /  2013-9-16 11:27  /  4869 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我们都知道递归要限定条件,还有注意递归的次数来避免没存溢出。
那么,这个限定条件或者这递归次数是否有个明确的限定值呢?
还是说这个是由计算机的内存大小决定?
那平时应该怎样避免这种内存溢出的情况?

评分

参与人数 1技术分 +1 收起 理由
黄兴旺 + 1

查看全部评分

3 个回复

倒序浏览
如何控制堆栈的大小?如果递归次数太大,如何避免产生堆栈溢出?

引起堆栈溢出的原因是, 分配了太多的函数指针,变量指针和参数,以致在堆栈里申请的内存数量不够用。

到目前为止,堆栈溢出最平常的原因是无终止的递归。

用户可以编写自己的代码以检测和防止堆栈溢出。例如,如果您的应用程序依赖于递归,则可以使用计数器或状态条件来终止递归循环。

评分

参与人数 1技术分 +1 收起 理由
黄兴旺 + 1

查看全部评分

回复 使用道具 举报
      递归的调用次数是没有明确值的,递归的调用次数与参数数量、函数的复杂程度都是相关的,就是不知道和计算机内存是不是相关,应该是java所分配的虚拟内存被用完了就溢出了。
      如果递归太多,可以考虑用循环算法去替代。如果循环支持不了,可以这样试试:1、将中间过程保存,利用进程多次进入,分别运算。2、找个好机器,调整进程限制,扩大进程对栈空间的参数配置,尽可能使用大的栈空间。
回复 使用道具 举报
递归,递归回溯。当这两个算法的空间复杂度很大时就会内存溢出.
java中内存溢出和解决问题的思路
原因有很多种,比如: 1.数据量过于庞大;死循环 ;静态变量和静态方法过多;递归;无法确定是否被引用的对象; 2.虚拟机不回收内存(内存泄漏); 说白了就是程序运行要用到的内存大于虚拟机能提供的最大内存就发生内存溢出了。 内存溢出的问题要看业务和系

  原因有很多种,比如:

  1.数据量过于庞大;死循环 ;静态变量和静态方法过多;递归;无法确定是否被引用的对象;

  2.虚拟机不回收内存(内存泄漏);

  说白了就是程序运行要用到的内存大于虚拟机能提供的最大内存就发生内存溢出了。 内存溢出的问题要看业务和系统大小而定,对于某些系统可能内存溢出不常见,但某些系统还是很常见的解决的方法,

  一个是优化程序代码,如果业务庞大,逻辑复杂,尽量减少全局变量的引用,让程序使用完变量的时候释放该引用能够让垃圾回收器回收,释放资源。

  二就是物理解决,增大物理内存,然后通过:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m的修改

  一、内存溢出类型

  1 、 java.lang.OutOfMemoryError: PermGen space

  JVM 管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在 JVM 启动时创建;非堆是留给 JVM 自己用的,用来存放类的信息的。它和堆不同,运行期内 GC 不会释放空间。如果 web app 用了大量的第三方 jar 或者应用有太多的 class 文件而恰好 MaxPermSize 设置较小,超出了也会导致这块内存的占用过多造成溢出,或者 tomcat 热部署时侯不会清理前面加载的环境,只会将 context 更改为新部署的,非堆存的内容就会越来越多。

  2 、 java.lang.OutOfMemoryError: Java heap space

  第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间 ( 即 -Xms) 是物理内存的 1/64 ,最大空间 (-Xmx) 是物理内存的 1/4 。如果内存剩余不到 40 %, JVM 就会增大堆到 Xmx 设置的值,内存剩余超过 70 %, JVM 就会减小堆到 Xms 设置的值。所以服务器的 Xmx 和 Xms 设置一般应该设置相同避免每次 GC 后都要调整虚拟机堆的大小。假设物理内存无限大,那么 JVM 内存的最大值跟操作系统有关,一般 32 位机是 1.5g 到 3g 之间,而 64 位的就不会有限制了。

  注意:如果 Xms 超过了 Xmx 值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

  垃圾回收 GC 的角色

  JVM 调用 GC 的频度还是很高的,主要两种情况下进行垃圾回收:

  当应用程序线程空闲;另一个是 java 内存堆不足时,会不断调用 GC ,若连续回收都解决不了内存堆不足的问题时,就会报 out of memory 错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。

  根据 GC 的机制,程序的运行会引起系统运行环境的变化,增加 GC 的触发机会。

  为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和 GC 的开销。显示调用 System.GC() 只能建议 JVM 需要在内存中对垃圾对象进行回收,但不是必须马上回收,

  一个是并不能解决内存资源耗空的局面,另外也会增加 GC 的消耗。

  二、 JVM 内存区域组成

  简单的说 java中的堆和栈

  java把内存分两种:一种是栈内存,另一种是堆内存

  1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;

  2。堆内存用来存放由 new创建的对象和数组

  在函数(代码块)中定义一个变量时, java就在栈中为这个变量分配内存空间,当超过变量的作用域后, java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由 java虚拟机的自动垃圾回收器来管理

  堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;

  栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活 性。

  java 堆分为三个区: New 、 Old 和 Permanent

  GC 有两个线程:

  新创建的对象被分配到 New 区,当该区被填满时会被 GC 辅助线程移到 Old 区,当 Old 区也填满了会触发 GC 主线程遍历堆内存里的所有对象。 Old 区的大小等于 Xmx 减去 -Xmn

  java栈存放

  栈调整:参数有 +UseDefaultStackSize -Xss256K,表示每个线程可申请 256k的栈空间

  每个线程都有他自己的 Stack

  三、 JVM如何设置虚拟内存

  提示:在 JVM中如果 98%的时间是用于 GC且可用的 Heap size 不足 2%的时候将抛出此异常信息。

  提示: Heap Size 最大不要超过可用物理内存的 80%,一般的要将 -Xms和 -Xmx选项设置为相同,而 -Xmn为 1/4的 -Xmx值。

  提示: JVM初始分配的内存由 -Xms指定,默认是物理内存的 1/64; JVM最大分配的内存由 -Xmx指定,默认是物理内存的 1/4。

  默认空余堆内存小于 40%时, JVM就会增大堆直到 -Xmx的最大限制;空余堆内存大于 70%时, JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置 -Xms、 -Xmx相等以避免在每次 GC 后调整堆的大小。

  提示:假设物理内存无限大的话, JVM内存的最大值跟操作系统有很大的关系。

  简单的说就 32位处理器虽然可控内存空间有 4GB,但是具体的操作系统会给一个限制,

  这个限制一般是 2GB-3GB(一般来说 Windows系统下为 1.5G-2G, Linux系统下为 2G-3G), 而 64bit以上的处理器就不会有限制了

  提示:注意:如果 Xms超过了 Xmx值,或者堆最大值和非堆最大值的总和超过了物理内 存或者操作系统的最大限制都会引起服务器启动不起来。

  提示:设置 NewSize、 MaxNewSize相等, “new”的大小最好不要大于 “old”的一半,原因是 old区如果不够大会频繁的触发 “主 ” GC ,大大降低了性能

  JVM使用 -XX:PermSize设置非堆内存初始值,默认是物理内存的 1/64;

  由 XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的 1/4。

  解决方法:手动设置 Heap size

  修改 TOMCAT_HOME/bin/catalina.bat

  在“ echo “Using CATALINA_BASE: $CATALINA_BASE””上面加入以下行:

  JAVA_OPTS=”-server -Xms800m -Xmx800m -XX:MaxNewSize=256m”
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马