虚拟机栈
2021-04-19 16:41:36 0 举报
AI智能生成
虚拟机栈超详细思维导图
作者其他创作
大纲/内容
虚拟栈概述
是啥
java处理指令的一块内存空间
每个线程创建时都会创建一个虚拟机栈,其内部保存一个个栈针
为啥
java指令基于栈,不同平台cpu架构不同,不能设计为基于寄存器的
优缺点
优点
跨平台
快速有效的分配存储方式访问速度仅次于栈
指令集小
容易编译
对栈来说不存在垃圾回收
缺点
性能差
实现相同功能代码更多
生命周期
生命周期与线程一致
作用
主管java程序的运行,保存的方法为局部变量(8种基本数据类型),部分结果,并参与方法调用和返回
局部变量VS成员变量
基本数据变量VS引用类型变量(类,数组,接口)
三个问题
java虚拟机官方允许java栈的大小是动态或者固定不变的
如果采用固定大小的java虚拟机栈,当请求的容量超过java允许的最大容量,会抛出一个stackOverFlowError
如果虚拟机是动态扩展的,并且尝试扩展时无法申请足够的空间,或者在创建新的线程时没有足够的内存去创建对应的栈,会出现OOM
栈的存储单位
栈中存储啥
每个线程都有自己的栈,栈中的数据都是以栈帧(stack frame)的方式储存
线程上正在执行的每个方法都对应一个栈帧
栈帧是一个内存区块,是一个数据集
复习一下面向对象
OOP的基本概念:类,对象
类中的基本结构field(属性,字段,域),method
栈运行的原理
1、操作只有两个操作,压栈和出栈
2、记住当前栈帧(current frame) 当前方法(current method)当前类(current class)
3、执行引擎运行的指令只针对当前栈
4、java放回的方式有两种,一种是正常返回,另一种是抛出异常(被cry catch包裹的不算)
栈顶缓存技术
栈的相关面试题
举例栈溢出的情况?(StackOverFlowError)
调整栈的大小,就能保证不出现溢出吗?
分配的栈内存越大越好吗?
垃圾回收是否会涉及到虚拟机栈?
方法中定义的局部标量是否线程安全?
什么是线程安全
代码追踪
参考idea中jclasslib的操作
方法的调用:解析与分派
虚拟机栈
又叫帧数据区
local variable table 局部变量表
slot(槽)
局部变量变的基本单位
槽的数据从index0开始,到长度-1结束
存放编译的各种基本数据类型
在局部变量表内,32位以内的类型只占用一个slot,包括returnAddress 64位的占两个slot
如果当前帧是构造方法或者实例方法那么该对象应用this将会放在index0的slot处,其余按照参数顺序继续排放
栈帧中的局部变量表是可以重复
栈帧中的局部变量表中的槽位是可以重复利用的
静态变量和局部变量的对比
按照变量分类
基本数据
引用数据
按照作用范围
局部变量
成员变量
实例变量
静态变量(类变量)
Local Variable Table
operand stack(操作数栈)
栈的实现方式
数组
链表
操作数栈是通过数组实现的
特点
后进先出
只有入栈(push)出栈(pop)操作
dynamic linking动态链接
指向运行时常量池的方法引用
为什么需要常量池呢?
常量池的通是为了提供高一些符号和常亮,便于指令识别
returnAddress(方法返回地址)
结束方式
正常执行退出
出现未处理的异常
无论哪种方式退出,在方法退出后都返回了该方法被调用的位置,正常退出,调用者的pc计数器的值作为返回值即调用该方法的指令的下一条指令的地址,通过异常退出的,返回地址要通过异常表确定
方法返回地址的本质
other(一些附加信息)
一些重点知识
符号引用转换为直接引用的过程
静态链接
动态链接
方法的绑定机制
早起绑定
晚期绑定
可以看具体例子-com.study.jvm.stack.localvariables.LocalVariables
补充说明
在栈帧中,与性能调优关系最密切的部分就是局部变量表
局部变量中的变量也是重要的垃圾回收的根节点,只要被局部变量表中直接或间接引用的对象都不会被回收
由于高级语言具备多态的特性,那么就具备早起绑定和晚期绑定两种绑定方式
com.study.jvm.stack.localvariables.LocalVariables
虚函数
方法的调用
非虚方法
同早起绑定,静态链接类似
静态方法、私有方法、final方法、实例构造器,父类的方法等都是非虚方法
虚方法
同晚期绑定,动态链接相似
非虚方法之外的都是虚方法
子类的多态性的使用前提
类的继承关系
方法的重写
方法调用的指令
该四条指令固话在虚拟机内部,方法的调用执行不可人为干预
由用户确定方法版本
invokestatic:调用静态方法,解析阶段确定唯一方法版本(属于静态链接)
invokespecial:调用<init>方法、私有方法及父类方法,解析阶段确定唯一法版本(属于静态链接)
invokevirtual:调用所有虚方法(除去final修饰的方法外都属于动态链接)
invokeinterface:调用所有接口方法(属于动态链接)
invokeDynamic:动态解析出需要调用的方法,然后执行(属于动态链接)
语言
静态语言
例如java:String str = “你好”;//如果不定义类型就会报错 重新赋与其他类型的值也会报错 str = 10;//错误
动态语言
例如JS: var name = \"这是个字符串\"// 后期一个队这个重新赋值 name = 10;
例如Python: info = 123.3; info = \"张三\"; //这里连参数的类型都不需要定义
简而言之:静态类型是判断自身的类型信息 动态语言是判断变量值的类型信息,变量没有类型信息,变量值才有类型信息
方法调用
方法重写的本质
找到操作数栈顶的第一个元素所执行对象的实际类型,记做E
在类型E中找到与常量中的描述符合简单名称都相符的方法,则进行访问权限效验,如果通过则返回这个方法的直接引用,查过程结束;如果不通过,则返回java.lang.IllegalAccessError异常
否则继承关系从下往上依次E的各个父类进行第二部的搜索和验证过程
如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError
虚方法表
为了提高性能(避免每次都往父类找),在方法区建立一个虚方法表(virtual method table)(非虚方法不会出现在表中,非虚方法是编译时就确定了调用方法就确定了)
虚方法表是在链接的阶段就产生的(在链接阶段中的解析阶段(符号引用转换为直接引用))
语言类型总览
强弱分
strongly
如果一种语言的所有程序都是well behaved——即不可能出现forbidden behaviors,则该语言为strongly typed。
weakly
否则为weakly typed。比如C语言的缓冲区溢出,属于trapped errors,即属于forbidden behaviors..故C是弱类型
动静分
dynamiclly
staticlly
0 条评论
回复 删除
下一页