欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

1运行时数据区

程序员文章站 2022-04-04 15:01:49
先来张图: 一、程序计数器:指向当前线程正在执行的字节码指令的地址(或者说行号)。每个线程都有一个自己的计数器。 为什么指向正在执行的字节码指令的地址?因为CPU会切换线程执行,当前线程可能会被挂起,被挂起的时候当前指令可能没执行完成,待CPU重新调度到该线程时,需要知道当前线程执行到哪了。 二、虚 ......

先来张图:

1运行时数据区

一、程序计数器:指向当前线程正在执行的字节码指令的地址(或者说行号)。每个线程都有一个自己的计数器。

为什么指向正在执行的字节码指令的地址?因为cpu会切换线程执行,当前线程可能会被挂起,被挂起的时候当前指令可能没执行完成,待cpu重新调度到该线程时,需要知道当前线程执行到哪了。

二、虚拟机栈:存储当前线程运行方法所需要的数据,指令和返回地址。(---->栈---->数据结构----->存储数据---->存什么数据?)
1运行时数据区

 

 

虚拟机描述的是java方法执行的内存模型:每个方法执行时会创建一个栈帧。栈帧的结构大致如下:(网上找来的图)

1运行时数据区

 

1.局部变量表:用于存放方法参数和方法内部定义的局部变量。(大小在编译时已经确定)

局部变量表以变量槽(slot)为 最小单位,boolean,byte,char,short,float,reference或returnaddress占一个slot,

long ,double占两个slot。

 举个例子:(某视频上的)

 1 public class helloworlddemo {
 2     // 常量、静态变量
 3     private final int i = 0;
 4     private static int k = 0;
 5     //成员变量
 6     private object obj=new object();
 7     private int sss=0;
 8     
 9     //局部变量
10     public void methodone(int i) {
11         int j=0;
12         int sum=i+j;
13         object acb=obj;
14         long start = system.currenttimemillis();
15         methodtwo();
16         return;
17     }
18 
19     public static void methodtwo() {
20         methodtwo();
21     }
22     public static void main(string[] args) {
23         methodtwo();
24     }
25 }

使用javap -c -v 命令反编译其class文件,可以看到methodone方法各变量在局部变量表的位置:

1运行时数据区

可以看出:this在0位置,i,j,sum等分别在1,2,3位置。(非静态方法0位置是this)

2.操作数栈:通常称为操作栈(后入先出),栈的最大深度在编译时已确定。

网上搜索了解methodone大概执行流程:

public void methodone(int);
descriptor: (i)v
flags: acc_public
code:
stack=2, locals=7, args_size=2
0: iconst_0 //将int类型常量0压入栈(虚拟机栈)
1: istore_2 //将int类型值存入局部变量2 (即程序中的j)(此时0会出栈)
2: iload_1 //从局部变量表1中装载int类型值(即i的值)(i值入栈)
3: iload_2 //从局部变量表2中装载int类型值(即j的值)(j值入栈)
4: iadd //执行add操作
5: istore_3 //将结果存入局部变量表3 (即sum)(结果出栈)
6: aload_0 // 将第一个引用类型本地变量推送至栈顶(非静态方法是this,静态方法是第一个引用类型变量)
7: getfield #25 // field obj:ljava/lang/object; //将栈顶的指定的对象的第25个实例域(field)的值(6到7不是很明白,this的值,按流程aload_0应该指的是obj这个对象)
(这个值可能是引用,这里就是引用)压入栈顶
10: astore 4 //将栈顶的值存入局部变量4 (即acb)
12: invokestatic #33 // method java/lang/system.currenttimemillis:()j //调用类的static方法
15: lstore 5 //将栈顶long型数值存入局部变量表5中(即start)
17: invokestatic #39 // method methodtwo:()v //调用本类static方法methodtwo()
20: return
linenumbertable:
line 13: 0
line 14: 2
line 15: 6
line 16: 12
line 17: 17
line 18: 20
localvariabletable:
start length slot name signature
0 21 0 this lcom/thomas/jvm/helloworlddemo;
0 21 1 i i
2 19 2 j i
6 15 3 sum i
12 9 4 acb ljava/lang/object;
17 4 5 start j

 

3.动态链接:运行时才确定真正的链接。比如在类内声明接口类型的变量  private  iusb usb;在方法内调用其do方法时,实际调用的是其具体某个实现类的do方法,这是在运行时才需要确定的,假如方法不执行就不必知道。

4.返回地址:出栈后去哪?返回地址确定

递归调用时有多少个栈帧?n个    递归会导致*error

三、本地方法栈:描述的是本地方法出栈入栈的过程,类比于虚拟机栈。native方法:简单的说,就是一个java调用非java代码的接口。

四、方法区:存储类信息,常量(1.7)静态变量,jit(即时编译器)编译后的代码(动态代理,在jvm运行时生成的代码,也要加载到内存中)。

五、heap(堆):存放对象实例。这里涉及到jvm内存模型(jmm),下一篇。