For investors
股价:
5.36 美元 %For investors
股价:
5.36 美元 %认真做教育 专心促就业
我们在前几期的文章中给大家简单介绍了java编程开发需要掌握的一些基础知识点等内容,而本文我们就来学习一下,java编程虚拟机栈入门知识分享。
一、程序计数器
众所周知,虚拟机处理多线程时,是通过轮流的切换线程,来获取cpu的执行机会的。在虚拟机执行程序的过程中,当线程执行到某一位置时,虚拟机将cpu的执行机会出让给了其他线程,此时原有线程的执行位置需要被记录下来,而新得到执行机会的线程,又需要提供上次执行的位置,以此来保证程序中的多个线程可以持续的并行的执行下去。
程序计数器的作用就是将各个线程下次所执行的(字节码)行号(准确来说是指令的地址)记录下来,以保证其下次执行时可以正确的执行。
根据程序计数器的作用,我们可以知道:
1、每个线程都在这个区域中都应该拥有一个只为自己提供服务的程序计数器,它们之间是独立存储,互不影响的存在。
2、我们还可以知道,程序计数器只记录字节码的行号,因此当线程执行本地方法(Nativemethod)时,计数器的值是空。
3、程序计数器所耗费的内存空间非常小,因此这个区域是不会抛出OutOfMemoryError错误的。
二、虚拟机栈
线程想要正常的运行下去,单靠程序计数器来记录行号是远远不止的。线程还需要拥有自己的运行空间,在这个空间中,虚拟机可以保存方法的执行顺序、方法的内部局部变量,方法在运算时,所需要的内存空间等。
在数据结构中,栈的特性满足方法的进入返回的结构的。而这块区域的主要作用就是线程在执行java方法时所需要记录的数据。因此我们将这块区域称之为虚拟机栈。但是要记住这里与我们在工作中通常指的栈并不等同,这个我会在后边介绍。
每一部分的作用如下:
(1)局部变量表:每一个方法都可以定义一个只属于自己的局部变量,当这个方法运行结束后,这个局部变量的生命周期也就宣告结束。所以每一个方法都应该拥有一个块属于自己的内存区域用来保存方法内部定义的局部变量。这块区域就是局部变量表,我们平常工作中所指的栈,实际上指的是虚拟机栈中的栈帧中的局部变量表。
(2)操作数栈:每个方法的内部都可以计算数据,而计算数据势必需要拥有一块内存区域,为虚拟机用来进行数值计算。因此在栈帧中,就需要有一块区域专门为当前方法计算数据使用,它就是操作数栈。
在每进行一次完整的计算之后,栈中的数据都已经出栈,所以操作数栈的空间在一个方法内部是可以反复使用的。所以虚拟机在分配内存大小时,只分配当前方法,单次完整计算所需要的大内存空间给当前栈帧,以减少内存的消耗。
同时为了增加运行效率,减少数据的不断复制,在大部分虚拟机的实现中,将当前方法的局部变量表和上层方法的操作数栈的内存形成部分重叠,从而减少参数的不断复制而引起的性能消费。
(3)动态连接:
虚拟机在执行方法时有两种形式被用来确定执行指令所对应的方法,
一种是类加载时,可以直接确定要执行的方法,譬如静态方法,私有方法,final方法等。这种形式叫做静态解析。
二种是在真正运行时,根据对象的真实引用来判断当前真正要执行的方法。这种形式称之为动态连接。
在字节码文件中,都存在一个常量池,在这个常量池中保存有大量的符号引用,这个符号引用是每一个方法的间接引用。在字节码指令的中,使用的是这个符号引用。但是在运行时阶段,肯定需要调用到要执行方法在内存中真实的地址。这就需要将间接引用转化成直接引用。而这里的“动态连接”就是为了保证在运行时阶段,方法可以正确的找到要调用的方法,每个栈帧将自己在运行时常量池中所对应的真实地址记录的位置。
这里需要注意的是,在栈帧中的动态连接和查找符号引用为真实引用中的动态连接,是两个概念。前者表示的是一个区域,后者表示的是一种查找方式。
(4)返回地址:
退出当前方法的方式有两种,一种是遇到返回指令时,正常的退出当前方法。另一种形式是遇到没有捕获而被抛出的异常。无论何种返回形式,在方法退出后,栈帧的顶端都应是当前退出方法的上层方法。同时上层方法的执行状态也需要根据当前的返回结果重新调整。所以每个栈帧可以利用“返回地址”这块区域帮助上层方法恢复状态。
(5)附加信息:对于虚拟机规范中没有申明的,拥有指定存放位置的信息可以由各个虚拟机自己决定,放置到这个区域中。
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!请读者仅作参考。更多内容请加抖音太原达内IT培训学习了解。