## 1. 运行时数据区的结构 ![](https://wangxblog.oss-cn-hangzhou.aliyuncs.com/usr/uploads/2020/05/1729374742.png) 每个JVM只对应一个Runtime实例 ## 2. 线程 JVM虚拟机允许一个应用程序创建多个线程并行执行 在HotSpot JVM中,每个线程都和本地操作系统本地线程进行直接的映射 ## 3.程序计数器 1).什么是程序计数器? >JVM中的PC寄存器是物理机器上的PC寄存器的一个模拟,存放下一条指令的位置 2).作用 >存储下一条指令的地址 ps:线程私有的,无GC,无OOM,其中native方法在PC中为undefined 3)常见面试问题 - 使用PC寄存器存储字节码指令地址有什么用? > 因为CPU在不断的切换进程,用PC寄存,就能在切换回来的时候知道从哪里继续执行程序 - 为什么PC寄存器是线程私有的 > 若不是私有的就会导致指令错乱,可能在CPU切换的时候运行别人的指令 ## 4.虚拟机栈 1).什么是虚拟机栈? > 主管Java程序的运行,它保存方法的局部变量,部分结果并参与方法的调用和返回 2).栈帧 >虚拟机栈的基本单位,一个栈帧对于一个方法 ps: 虚拟机栈是线程私有的 - 局部变量表 - 操作数栈 - 动态链接(指向运行时常量池的方法引用) - 方法返回地址(方法正常退出或异常退出的定义) 3).开发中遇到那些异常? >允许设置Java栈为固定值,若超过设置的最大容量就会发送StackOverflowError 若动态添加,在扩容内存大于能分配的内存的时候就会产生OutOfMemoryError 4)设置参数 >-Xss 设置最大的栈大小 如-Xss 256k,默认大小约为linux 1024KB Mac 1024KB 5). 一些附加信息 >①.局部变量表 定义一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据包括基本数据类型,对象引用以及returnaddress类型,在编译时就确定下来了,不存在数据安全问题 最基本的单位slot,32位以内的数据类型只占用一个slot,64位的占用2个slot 在构造方法或者实例方法中会将对象引用this存放在index为0的slot中,其余参数按照顺序排序。 slot可以重复利用,局部变量使用前必须显式赋值 **局部变量表是重要的GCRoot,只要被局部变量表直接或者间接引用的变量不会被GC回收** >②.操作数栈 基本单位为栈深度,数组实现的栈 栈顶缓存技术,缓存在cpu的寄存器,降低内存的IO次数,提升执行引擎的效率 >③.动态链接 在JVM中,将符号引用转换为调用方法的直接引用与方法绑定机制有关。 - 动态链接 只是在运行时可知,对应的方法绑定机制为:早期绑定和晚期绑定,绑定时一个字段、方法或者类的符号引用呗替换为直接引用的过程,这仅仅发生一次 - 早期绑定(如调用父类构造器) 目标方法在编译器可知,在运行期不变 - 晚期绑定(如父类调用方法等) 与之相反 - 静态链接 一个字节码文件被转载如虚拟机时,如果被调用目标方法在编译器可知 **具备多态性就具有早期绑定和晚期绑定两种方法** ## 5.虚方法和非虚方法 1).非虚方法:方法在编译期间就确定好了调用版本,这个版本运行时是不可变的 如:静态方法,私有方法,final方法,实例构造器,父类方法都是非虚方法 2).虚方法 其他方法均称为虚方法 ## 6.方法重写的本质 step1.找到操作数栈栈顶的第一个元素所执行的对象实际类型记为C step2.若类型C中找到常量中的描述符合并且简单名称都符合的方法,则进行访问权限校验,如果通过返回这个方法的直接引用,查找过程结束 step3.否则按照继承关系从下往上一次对各个父类进行搜索和验证过程 step4.始终未找到,则抛出java.lang.AbstarctMethodError 每次调用都会进行这么一个过程,为了提升性能,JVM在类中方法区建立一个虚方法表,来用索引代替查找 ## 方法返回地址 1)作用 > 存放该方法PCC寄存器的值 2).方法结束的方式 > ①正常执行完成 ②出现未处理的异常 无论哪种方式退出在方法退出后都会返回到该方法被调用的位置,方法正常退出,调用者的PC寄存器的值作为返回地址,即调用下一条指令的地址。而异常退出,返回地址是通过异常表确定的,栈帧中一般不会保存这部分信息 最后修改:2020 年 05 月 06 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏