JAVA内存区域及内存溢出异常——总结

JAVA内存划分

JAVA虚拟机在运行程序的时候会将内存划分成几个区域,这些区域有各自的用途,包括以下几个区域

  程序计数器、虚拟机栈、堆、方法区(包含常量池)

其中和线程保持一致的有程序计数器,虚拟机栈,数据共享的区域是堆和方法区

1、程序计数器是记录线程指令执行的相关步骤的计数器,每个线程各自拥有一个程序计数器,程序计数器的长度是固定的,也是这几个内存划分中不会有OMM和SOE异常的内存区域

2、虚拟机栈(此处包含本地方法栈)可以在模糊意义上和我们平常所说的栈相互关联起来,这个区域的生命过程和线程是保持一致的,这个虚拟机栈描述的是JAVA方法执行的内存模型,每个方法执行都会保存局部变量表、操作数栈。。。。(一般我们关注的是局部变量表),需要知道的是局部变量表中包含的是基本数据类型以及引用类型,此处的引用可以是直接指向一个对象的指针引用,也可是一个句柄(中间量,句柄中存放相关对象的指针),需要注意的是方法中的局部变量在编译的期间已经确定了相关的大小,

Q:既然是编译期间就计算好了相关的大小,那么为什么还有stackOverflowError和OMM异常呢?

A:由于线程执行的时候并不是一个方法执行到底的,方法中会调用其他的方法,而在方法不退出的时候局部变量还是保存在栈中的,如果是相关的递归的调用,方法栈比较深,这样需要保存局部变量的内存就会变得大了起来,就会产生相关的异常

3、堆 堆一般来说应该是JVM中内存最大的一块区域,这个区域保存着所有的实例信息,且被所有的线程所共享的一块内存区域,这个区域也是GC回收的重点区域

4、方法区 这个区域保存着类的相关信息、常量池、静态变量,也是所有线程所共享的一块区域

OMM异常信息(OutOfMemoryError)

 除了程序计数器的内存区域不会产生OMM异常外,所有其他的内存划分区域都会产生OMM异常

1、栈空间产生OMM异常,栈空间的OMM异常和StacKOverFlowError异常本质上都是内存不够用的异常,一般的产生原因是无限制的递归

2、堆空间的OMM异常,一般是多线程下的对象创建比较多,且不释放相关对象的引用,导致GC无法回收,产生OMM

3、方法区的异常 相关的动态字节码生成技术,产生大量的class信息,导致内存不够产生异常,当然在1.7之前的版本中,String的intern的本地方法第一次产生的字符串常量在堆上面创建对象之后,会拷贝相关的信息到常量池中,所以String的intern方法返回的是常量池中的引用。如果产生足够多的常量也会产生OMM异常

转载于:https://my.oschina.net/guanhe/blog/1576273

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值