前段时间看了一点《深入理解jvm》,记下笔记,总结一下自己的理解
内存模型
黑色的部分(方法区和堆)为所有线程共享,白色部分(虚拟机栈、本地方法栈、pc计数器)为线程私有
pc计数器
学过计算机组成原理的应该对这个有印象。pc计数器存放的是计算机下一条指令的地址,计算机读取pc计数器中的值,依据这个值去指令寄存器读出下一条指令,然后执行。该区域为线程私有。
虚拟机栈
这块区域就是常说的栈。每个方法在执行的同时,会创建一个栈帧,用于存放局部边量表、操作数栈、动态连接、方法出口等信息。每个方法的调用对应者一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部边量表中存放基本类型(int、char、float….)和引用类型数据,在分配栈帧空间时,局部边量表的大小是确定的。64位的long和double占两个局部变量的空间,其余类型只占一个。
虚拟机栈可能出现两种异常状况:
- 请求的虚拟机栈深度大于规定的栈深度,抛出StackOverflowerError
- 如果虚拟机栈允许动态扩展,扩展时无法申请到足够的内存,会抛出OutOfMemoryError。
本地方法区
本地方法区和虚拟机栈很相似,不过java虚拟机栈是用来运行java方法的,而本地方法区是用来执行本地方法(native关键字定义)的。
堆
堆是用来存放java对象实例的区域,是线程共享的。
java堆是垃圾收集器管理的主要区域,从内存回收的角度讲,堆可以被分为新生代和老年代:
- 刚实例化出来的对象放在新生代
- 在新生代中熬过一次gc的对象会被移动到老年代
堆的大小可以通过jvm参数进行设置:-Xms堆的最小值 -Xmx堆的最大值
当堆没有内存完成实例分配,且堆大小无法再扩展时,抛出OutOfMemoryError
方法区
方法区存放已被加哉类信息、静态变量、常量等数据。
当方法区无法满足内存分配要求时,抛出OutOfMemoryError。
直接内存
java方法运行过程中可能会直接分配堆外内存,也就是计算机的内存。
当本机内存无法满足内存需要时,也会抛出OutOfMemoryError异常