JVM运行时数据区:虚拟机栈(栈)

虚拟机栈

栈是线程独立的,在线程中对应方法的调用:一个方法对应一个栈帧、一个线程对应一个栈;栈的生命周期同线程。
其作用可以和堆进行对比,堆是存储单位,而栈是运行时单位。

虚拟机栈运用的栈结构导致它不用GC,因为只会对栈顶元素进行操作;但会出现OOM即内存溢出(栈过大)

栈的异常根据其大小确定形式而不同:
栈大小可动态、可固定。
固定栈大小:会出现SOF、StackOverFlowError错误(因为一个方法对应一个栈帧,在递归等方法过量执行的情况下会出现此错误)(固定大小可以通过-Xss指令进行规定)
动态栈大小:当栈申请过大会造成OOM错误。

栈帧:

一个栈帧即代表一个方法,有方法执行即向栈中压入一个栈帧,执行完再弹出。
栈帧由局部变量表、操作数栈、方法返回地址、动态链接、(附加信息)组成。

局部变量表(栈帧中主要成分):
该表用数组结构(像char、boolean、int、byte等数据都能看作是int数据)
用于存储方法参数、局部变量等(八大基本类型、对象引用地址、返回地址)
该表大小在编译时就已经确定了,存在方法的code属性下一个数据(字节码文件)。(Code下存储方法属性、局部变量属性(生效位、生效长度))

局部变量存储单元:slot:
32位数据占一个slot,64位(double、long)占2个
若当前帧由构造方法或实例方法(this.xxx)创建,还需要this对象,也要存入局部变量表中
slot可以重复使用,即当在方法内部for循环内定义了一个变量开辟一个slot,当跳出循环该变量销毁,该slot可以被其他局部变量使用。

操作数栈:
保存计算过程中的中间结果,也作为计算过程中变量的临时存储空间。
有最大深度,当方法执行、操作数栈也生成但为空。
和slot一样,32位数据占一个单位,64位(double、long)占2个

在字节码文件中:
ipush、iload:是对操作数栈进行操作,取出数据进行iadd
istore:是对局部变量表操作

当方法有返回值时,会将返回值存入操作数栈中。

对于栈,java做了栈顶缓存:因为栈指令多,对栈读写频繁,用寄存器缓存栈顶效率更高。

动态链接:
每个栈帧内部都有一个指向运行时常量池中该帧所属方法的引用。这一步就是将符号引用变为直接引用的直接体现。

为了将链接解释的更清楚,先了解一下方法的相关知识:
首先方法的调用本质是将符号引用转为直接饮用,地址和真正的方法之间链接分两类:
静态链接:在编译期间链接关系就确定,运行时不变
动态链接:在运行时关系才确定

对应的符号引用转为直接引用的绑定情况也分两种:
早期绑定:同静态链接,编译期间确定
晚期绑定:同动态链接

例如:
父类Animal 子类Cat、Dog继承于Animal
调用时需要Animal类,此处传入Cat、Dog就属于晚期绑定

在静态、早期绑定的方法对应非虚方法:即静态、私有、构造器、final修饰等不能被重写的方法,以及直接调用父类方法时(super.xxx)该xxx方法也是非虚方法。

虚方法对应晚期绑定、动态链接:例如调用类自身的函数,因为不确定是否重写,属于虚方法。

在字节码文件中对应不同方法使用的invoke有5类,其中invokedynamic是java动态的体现。

代码的静态动态:
静态:String info = “abc”; 静态语言以String这个标记的类型为准,即后面赋值必须为String类型
动态:info = “abc”; 动态语言以后面的值为准,若为字符串,则前面变量数据类型就是字符串。

java本身是静态类型语言,但lambda表达式的引用,实际可以看做动态的一种引入,类的具体信息由lambda表达式内容确定。

方法重写的本质:
方法调用时从自身开始向上查询信息相同的方法。
但是若每次调用都这么查找就太浪费了,于是在方法区创建了一个虚方法表(在解析时创建),下次调用直接查表即可。

上述内容主要目的是理解方法的符号引用转为直接引用的过程,该过程发生在类加载的链接时期,存储在这个方法对应栈帧的动态链接处。

方法返回地址:
记录代码返回时继续的位置。
即方法退出后,代码应该从哪里继续执行。
退出又分为正常退出和异常退出。
异常退出时需要在异常表中去查询代码的继续位置。

注:局部变量是否线程安全:局部变量若逃逸(即其生效区域不仅是方法内),则可能线程不安全

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔幻音

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值