JVM内存溢出参数调优

JVM内存溢出分为两种情况:OutOfMemoryErrorStackOverflowError

  • OutOfMemoryError是在程序无法申请到足够的内存的时候抛出的异常
  • StackOverflowError是线程申请的栈深度大于虚拟机所允许的深度所抛出的异常

java.lang.OutOfMemoryError:Java heap space 堆内存溢出
解决办法:设置堆内存大小,设置jvm值的方法是调大-Xms(堆的最小值),-Xmx(堆的最大值)

java.lang.StackOverflowError 栈内存溢出
栈溢出产生于递归调用,循环遍历是不会的,但是循环方法里面产生递归调用, 也会发生栈溢出。解决办法:
设置线程最大调用深度:-Xss5m

内存溢出发生的区域

  • Program Counter Regster(程序计数器):每一个用户线程对应一个程序计数器,用来指示当前线程所执行字节码的行号。由程序计数器给文字码解释器提供下一条要执行的字节码的的位置。根据jvm规范,这个区域不会发生内存溢出
  • Java stack(java 虚拟机栈):这个区域是最容易出现内存异常的区域,每一个线程对应生成一个线程栈,线程每执行一个方法的时候,都会创建一个栈帧,用来存放方法的局部变量表,操作树栈,动态连接,方法入口。jvm规范对这个区域定义了两种内存异常。如果虚拟机在扩展栈时无法申请到足够的内存空间则抛出OutOfMemoryError如果线程请求的栈深度大于虚拟机所允许的最大深度,将会抛出StackOverflowError
  • Native MethodStack(本地方法栈):和虚拟机栈一样,不同的是处理的对象不一样,虚拟机栈处理java的字节码,而本地栈则是处理的Native方法。其他方面一致
  • Heap(堆):前面说了堆是所有线程都能访问的,随着虚拟机的启动而存在,这块区域很大,因为所有的线程都在这个区域保存实例化的对象,因为每一个类型中,每个接口实现类需要的内存不一样,一个方法内的多个分支需要的内存也不尽相同,我们只有在运行的时候才能知道要创建多少对象,需要分配多大的地址空间。GC关注的正是这样的部分内容,所以很多时候也将堆称为GC堆。堆中肯定不会抛出StackOverflowError类型的异常,所以只有OutOfMemoryError相关类型的异常
  • Method Area(方法区):用于存放已被虚拟机加载的类信息,常量,静态方法,即使编译后的代码。由于早期的 Hotspot JVM 实现,很多人习惯于将方法区称为永久代(Permanent Generation)。这个区域只能抛出OutOfMemoryError类型的错误,OutOfMemoryError: PermGen space。
解决方法: 手动设置MaxPermSize大小修改TOMCAT_HOME/bin/catalina.sh
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m"

内存泄漏和内存溢出的区别和联系

1、内存泄漏指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出
2、内存溢出指程序申请内存时,没有足够的内存供申请者使用,此时就会报错OOM
3、内存泄漏的堆积最终会导致内存溢出

猜你喜欢

转载自blog.csdn.net/ThreeAspects/article/details/105777619