怎么自己做网站游戏,南宁做网站找哪家公司,玛沁县网站建设公司,建网站手机软件背景#xff1a;由于跨平台的设计#xff0c;java指令都是根据栈来设计的。不同平台CPU架构不同#xff0c;所以不能设计为基于寄存器。
栈是运行时单位#xff0c;而堆是存储的单位。即#xff1a;栈解决程序运行的问题#xff0c;即程序如何执行#xff0c;或者说如何… 背景由于跨平台的设计java指令都是根据栈来设计的。不同平台CPU架构不同所以不能设计为基于寄存器。
栈是运行时单位而堆是存储的单位。即栈解决程序运行的问题即程序如何执行或者说如何处理数据堆解决是数据存储的问题即数据怎么放放在哪。
栈中可能出现的异常java栈的大小可以是动态的也可以是固定不变的。
如果采用固定大小的虚拟机栈那么如果线程请求超过栈容量会出现StackOverflowError异常。
如果java虚拟机可以动态扩展当无法申请扩展到足够的内存的时候会抛出OOMOutOfMemoryError)异常。
栈的运行原理
JVM直接堆Java栈的操作只有两个就是入栈和出栈遵循先进后出的原则所以没有GC垃圾回收。
java栈中存储的数据是栈帧一个活动线程的一个时间点上只有一个活动的栈帧如果在方法中调用了其他方法那么新的栈帧会被创建出来放在栈的顶端成为新的栈帧。
不同线程中所包含的栈帧是不允许存在相互引用的即不可能在一个栈帧之中引用另外一个线程的栈帧。
如果当前方法调用了其他方法方法返回时当前栈帧会传回此方法的执行结果给前一个栈帧接着虚拟机会丢弃当前栈帧使得前一个栈帧重新称为当前栈帧。
java方法有两种返回函数的方式一种是正常的函数返回使用return指令另外一种是抛出异常不管哪一种方式都会导致栈帧被弹出。
栈的内部结构
1局部变量表
2操作数栈
3动态链接
4方法返回地址
5一些附加信息
2 局部变量表
定义为一个数字数字主要用于存储方法参数和定义在方法体内的局部变量。
因为时定义在线程私有的虚拟机栈上所以很多时候不存在线程安全问题当局部变量作为函数参数传递一点点牵强、作为函数返回值时会出现线程安全问题。
局部变量表所需的容量大小是在编译期间确定下来的并保存在方法的Code 属性的maximum local variables数据项中。在方法运行期间是不会改变局部变量表的大小。
局部变量表中的变量只在当前方法调用中有效在方法执行时虚拟机通过局部变量表完成参数值到参数变量列表的传递过程。在方法调用结束后随着方法栈帧的销毁局部变量表也会随之销毁
Slot
局部变量表的最基本的存储单元就是slot槽
在局部变量表里32位以内的类型只占用一个slot包括returnAddress类型-存储的时候都是以int类型存储64位的类型long和double占用两个slot。
jvm会为局部变量中每一个slot都分配一个访问索引通过整访问索引可以成功范文到局部变量表中指定的局部变量
如果当前帧时由构造方法或者实例方法创建的非静态方法那么该对象的引用this将会存放在index为0的slot处。 slot的 重复利用
栈帧中的局部变量表中的槽位时可以重复利用的如果一个局部变量过了其作用域如类里面的代码块后面申请的局部变量就可能重复利用过期的局部变量的槽位。 局部变量与静态变量的对比
静态变量的初始化有两个阶段第一次是在准备阶段会对其分配存储空间和默认的初始化值第二次是在初始化阶段赋予程序员在代码中定义的初始值。
局部变量不存在系统初始化的过程所以一旦定义必须认为进行初始化不然无法使用。
3 操作数栈
操作数栈在方法执行过程中根据字节码指令往栈中写入数据或提取数据。主要用于保存计算结果过程的中间结果同时作为计算过程中的变量临时的存储空间。
操作数栈中可以存储任意类似的java数据32bit的类型占用一个栈单位深度64位的类型占用两个栈单位深度。
如果调用的方法带有返回值其返回值会被压入当前栈帧的操作数据栈中并更新PC寄存器中下一条需要执行的字节码指令。
java虚拟机的解释引擎是基于栈的执行引擎其中的栈就是操作数栈
4 动态链接
每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是支持当前方法的代码能够实现动态链接。比如invokedynamic指令。java属于静态语言是判断变量本身类型信息java8中lambda的出现invokedynamic指令的生成使得java有了直接生成的方式有了一个动态语言的特性。
在java源文件被编译到字节码文件中时所有变量和方法引用都作为符号引用保存在class文件的常量池里动态链接就是为了将这些符号引用转换位调用方法的直接引用。
5 方法调用
在jvm中将符号引用转换位调用方法的直接引用与方法的绑定机制相关。
静态链接当一个字节码文件被装入jvm内部的时候如果被调用的目标方法在编译期可知且运行期间保持不变这种情况下将调用方法的符号引用转换位直接引用的过程称为静态链接。
动态链接如果被调用的方法在编译期无法被确定下来也就是说只能够在程序运行期间将调用方法的符号引用转化位直接引用。