Java虚拟机栈和本地方法栈

Java虚拟机栈

Java虚拟机栈它也是线程私有的一块内存区域,所以生命周期自然和线程相同。

每个方法在执行的时候,Java虚拟机栈都会同步生成一个栈帧,然后再将这个栈帧压入Java虚拟机栈中,所以Java虚拟机栈主要保存的就是这个栈帧。

栈是一种先进后出的数据结构,所以Java虚拟机栈他只会先处理位于栈顶的栈帧,而位于栈底的栈帧(也就是最先入栈的栈帧)只会等待其上面的栈帧处理完毕了才会被处理。

当一个方法从调用到执行完毕,就意味着一个栈帧从Java虚拟机栈中从入栈到出栈的过程。

栈帧

栈帧主要保存局部变量表、操作数栈、动态连接、方法出口这几类数据。

局部变量表

局部变量表的大小

在编译程序代码的时候,就可以确定栈帧中需要多大的局部变量表了,具体大小可以在编译后的Class文件中看到了

即,局部变量表的大小,是在编译的时候就确定了。

局部变量表的容量

局部变量表的容量是以**槽(Slot)**为单位的,每个槽可以存储多大的空间是有虚拟机实现的(比如:32位长度、64位长度等等)

一般都是用32位长度的内存空间来实现,那么64位的long和double是占2个槽的,其余的不足32位长度的数据类型则占一个槽(包括引用类型和返回地址(returnAddress)都只占一个槽)

PS:或许这就是设置32位长度为一个槽的原因吧,为了节省空间,当然,纯属个人猜测

在方法执行的时候,虚拟机是用局部变量表完成参数值到参数变量列表的传递过程的,如果执行的是实例方法,局部变量表第0位索引的槽默认是用于传递方法所属对象实例的引用(在方法中可以用this关键字来访问这个隐含的函数)

这些可能有些难以理解

实例方法其实就是普通方法,而类方法是带static修饰的静态方法,静态方法是在初始化类的时候直接创建的,调用的时候直接用类名.(点)方法就可以了,而实例方法得先new出对象了才能通过对象调用。

在一个方法中,你可以直接用this来调用该对象的其他变量或方法,因为该对象就是保存在局部变量表中的第0位索引的位置上,可以直接通过this访问该对象。

看完这两段之后再看上面的可能就会好理解多了

操作数栈

  • 和局部变量表一样,操作数栈的大小,同样是在编译的时候就确定了大小
  • 当栈帧被创建的时候,操作数栈是空栈,操作数栈的每个项都可以存放JVM中的数据类型,其中double和long占2个栈深
  • 方法执行的过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是入栈和出栈操作
  • 操作数栈调用其他返回结果的方法时,会把结果push到栈上(通过操作数栈来进行参数传递)

动态连接

  • 每个栈帧都包含一个指向运行时常量池中该所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接
  • 在类加载阶段中的解析阶段会将符号引用转为直接引用,这种转发也称为静态解析。另外的一部分将在运行时转化为直接引用,这部分称为动态连接

返回地址(returnAddress)

当方法开始执行后,只有两种方式可以退出:方法返回指令异常终止



本地方法栈

本地方法栈和java虚拟机栈所发挥的作用是非常相似的,其区别就是

  • java虚拟机栈为虚拟机执行Java方法(也就是字节码)服务
  • 本地方法栈则是为虚拟机使用到的本地方法服务

StackOverflowError和OutOfMemoryError异常

Java虚拟机栈

  • 如果线程请求的栈深度大于虚拟机所允许的深度,则会抛出StackOverflowError异常
  • 如果Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常

本地方法栈
与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值