jvm初探

1.jvm是什么?jvm是用来做什么的?

我们可以这样简单的理解。你编写一个.java文件,经过编译后生成.class文件。.class文件是与平台无关的字节码,JVM的作用就是执行字节码的。JVM是一个抽象的计算机,和实际的计算机一样,具有指令集,并使用不同的存储区域,他负责执行指令,管理数据、内存与寄存器。

2.jvm什么时候产生?

当启动一个java程序时,一个虚拟机就诞生了,当运行完程序,jvm就死亡了。如果在一个计算机上同时运行三个java程序,那么将得到三个jvm,每个jvm都有自己的指令集、寄存器、栈、垃圾回收堆、存储区等。

3.jvm运行机制

3.1jvm的存储机制

当jvm运行一个程序时,需要内存来存储很多东西,如:字节码、从已装载的class文件中得到的其他信息、程序创建的对象、传递给方法的参数等等,Jvm把这些东西都存储到几个“运行时数据区”中,便于管理。某些运行时数据区是由程序中所有线程共享的,还有一些则只能由一个线程拥有。每个jvm都有一个方法区与一个堆,它们由jvm中的所有线程共享。jvm中的每个线程都有一个PC寄存器与一个java栈,PC寄存器的值总是指向下一条将被执行的指令,java栈存储java方法调用的状态,如局部变量、实参等。jvm没有寄存器,使用java栈来存储中间数据。

(1)方法区

当jvm装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件(一个线性二进制数据流),然后将它传输到jvm中,紧接着jvm提取其中的类型信息,并将这些信息存储到方法区。方法区使用示例如下

class Lava{
       private int speed=5;
}

class Volcano {
       public static void main(String[] args) {
              Lava  lava=new Lava();
              lava.flow();
     }
}
步骤1:要运行Volcano程序,首先告诉虚拟机“Volcano”这个名字,然后jvm找到并读入相应的class文件“Volcano.class”

步骤2:jvm从class文件里的二进制数据中提取类型信息并放到方法区中。

步骤3:通过执行方法区中的字节码,jvm开始执行main()方法,在执行中,它会一直持有指向当前类(Volcano类)的常量池的指针。

步骤4:main()的第一条指令告知jvm,列在常量池第一项的类分配足够的内存。常量池第一项是一个对Lava类的符号引用,然后检查方法区,看Lava类是否被装载。当jvm发现没有装载过名为“Lava”的类时,开始检查并装载“Lava.class”,并把其中的二进制数据提取的信息放到方法区中。

步骤5:jvm以一个指向方法区Lava类数据的指针来替换常量池第一项(就是字符串Lava),以后接可以用这个指针快速的访问Lava类

步骤6:jvm为一个新的Lava对象分配内存。使用Volcano类常量池的第一项指针来访问Lava类型信息,找到其中记录的这样一个信息:一个Lava对象需要分配多少堆空间

步骤7:jvm确定了一个Lava对象的大小后,就在堆上分配这么大小的空间,并把这个对象的变量speed初始化为默认值0.

步骤8:把新生成的Lava对象的引用压到栈中,main()方法的第一条指令就完成了

步骤9:执行下一条指令,将speed对象初始化为正确的初始值5

步骤10:调用Lava对象的flow()方法

(2)堆

java程序在运行时创建的所有类实例或数组都存放在同一个堆中。

(3)PC寄存器

对于一个运行中的java程序而言,其中的每一个线程都有它自己的PC寄存器。PC寄存器的内容总是下一条将被执行指令的“地址”。

(4)java栈

每启动一个线程,java虚拟机就会为其分配一个java栈。java栈以帧为单位保存线程的运行状态。栈帧有三部分组成:局部变量区、操作数栈、帧数据区


4.模拟

class Act{
      public static void doMathForver() {
             int i=0;
             for(;;) {
                    i+=1;
                    I*=2;
             }
      }
}
下面的模拟展示了当前帧的局部变量、操作数栈、PC寄存器,以及方法区中的字节码,

每按一下step,就执行一条指令,pc计数器指向下一条将要执行的指令,下面来具体看看每一条指令执行的操作

doMathForver()方法只有一个局部变量i,

(1)iconst_0将0入栈


(2)istore_0将0出栈,存贮在局部变量区


(3)iinc:把i加上1


(4)iload:把局部变量的值压入操作数栈


(5)iconst_2:把2压入操作数栈


(6)imul:把操作数栈顶部的两个int弹出,执行乘法运算,再把结果压入


(7)istore_0:把乘法结果弹出,放入到局部变量中


goto:把程序计数器送回到iinc指令。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值