美文网首页
深入理解Java虚拟机_02_Java内存区域与内存溢出异常

深入理解Java虚拟机_02_Java内存区域与内存溢出异常

作者: 传达室马大爷 | 来源:发表于2020-04-01 17:17 被阅读0次

运行时数据区域

程序计数器
  • 每个线程都拥有自己独立的程序计数器,属于线程私有的内存区域
  • 当前执行的是Java方法,则计数器记录的是正在执行的虚拟机字节码指令地
  • 当执行的是native方法时,则这个计数器为空
  • 不会抛出异常
Java虚拟机栈
  • 线程私有,生命周期与线程相同
  • 每个方法执行的同时会创建一个栈帧,用于存储操作局部变量、操作数栈等,每个方法的执行过程实际上是栈帧在虚拟机栈中入栈出栈的过程
  • 当线程请求的栈深度大于虚拟机规定的最大值时,抛出StackOverflowError异常
  • 当虚拟机栈动态申请内存无法满足时,抛出OutOfMemoryError异常
本地方法栈
  • 线程私有区域
  • 与Java虚拟机栈类似,Java虚拟机栈作用于Java方法,而本地方法栈作用于Native方法
堆空间
  • 线程共享区域
  • 用于存放对象实例,所有对象实例和数组都要在堆上分配
  • 堆空间分为Eden区、From Survivor区、To Survivor区
  • 当堆空间动态申请内存无法满足时,抛出OutOfMemoryError异常
方法区
  • 线程共享区域
  • 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码数据等
  • 当方法区无法申请内存时,抛出OutOfMemoryError异常
运行时常量池
  • 属于方法区的一部分
直接内存
  • NIO可以使用native函数直接分配堆外内存,然后通过存储在堆内的DirectByteBuffer对象作为这块内存的引用
  • 本机直接内存不受Java堆大小的控制,但如果直接内存+虚拟机分配的内存总数大于机器物理内存时,会抛出抛出OutOfMemoryError异常异常

对象的访问方式

通过句柄访问

Java堆中有相关的句柄池,java栈reference保存着句柄池中具体句柄的地址,句柄中保存有指向堆中对象实例的指针和到对象类型数据的指针

image
直接使用指针访问

Java栈reference中保存堆中对象实例的指针,对象实例中存有到对象类型数据的指针


image
句柄访问和指针访问对比
  • 句柄访问的好处是Java栈reference中保存的是句柄的地址,当对象被移动时,只会改变句柄中指向堆中对象实例的指针,而reference本身保存的句柄地址不需要修改
  • 直接指针访问的好处是速度更快,节省了一次指针定位的时间开销,HotSpot虚拟机采用直接指针访问方式

相关文章

网友评论

      本文标题:深入理解Java虚拟机_02_Java内存区域与内存溢出异常

      本文链接:https://www.haomeiwen.com/subject/rrvauhtx.html