JVM之类加载机制

在Java中,只有我们创建的类被JVM加载之后,我们才能够使用。

一、类加载时机

类加载过程:

1、加载→2、验证→3、准备→4、解析→5、初始化→6、使用→7、卸载(其中,1,2,3,5,7这几个步骤顺序是确定的,但是解析、使用则没有确定;比如解析阶段不一定必须在初始化之前或者准备之后,它可能出现在初始化之后。)

什么情况下JVM会进行类加载操作?

1、遇到new、getstatic、putstatic、invokestatic这4跳字节码指令时,翻译过来就是,使用new关键字实例化对象的时候、读取或者设置一个类的静态字段(常量除外)的时候,以及调用一个类的静态方法的时候(PS:只有对应的类才会加载,比如,如果子类调用父类的静态字段,那么子类不会被加载,它的父类会被加载)。

2、使用java.lang.reflect包的方法对类进行反射调用的时候。

3、初始化一个类,发现其父类没有被初始化时,那么会先触发其父类的初始化。

4、JVM启动,包含了main函数的类会被初始化。

5、动态语言支持时(与1类似)。

二、加载

1、通过类的全限定名来获取定义此类的二进制字节流。

2、讲这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(就是这个类的类变量、字段、方法、方法参数、修饰符等信息保存在方法区)。

3、生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口(方法区存储的类的类变量、字段、方法、方法参数等信息通过Class对象来获取)。

三、验证

1、文件格式验证。2、元数据验证。3、字节码验证。4、符号引用验证。

四、准备

正式为类变量分配内存并设置类变量(类变量,即静态变量,实例变量不会被分配内存)的初始值(初始值不等于代码中设置的值,java中,每一种类型都有零值,这个时候设置初始值就是把变量设置为零值,比如int类型为0,long类型为0L,boolean类型为false等)。

五、解析

1、类或接口的解析。2、字段解析。3、类方法解析。4、接口方法解析。

六、初始化

在初始化阶段,就会完成代码设置的值的赋值。显示执行类构造器(不是构造函数,而是比构造函数优先一级的类构造器),类构造器<clinit>方法,执行这个方法,会优先收集这个类中所有的静态变量和静态代码块,然后对它们进行赋值,这也是为什么静态变量可以不用实例对象,而直接用类进行访问的原因。然后才是init方法,构造函数的执行,字段的赋值等。

七、类加载器

对于任意一个类,都需要由加载它的类加载器和这个类本身一桶确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。所以,比较俩个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个JVM加载,只要加载他们的类加载器不同,这两个类就不想等。

双亲委派模型:最顶层类加载器为 启动类加载器,第二层为 扩展类加载器,第三层为 应用程序类加载器, 第四层为自定义类加载器。这个逻辑比较简单,就是,当一个类需要加载的时候,它直属的类加载器首先不会自己加载这个类,而是扔给上一层加载,依次往上,一直到顶层的启动类加载器,只有当上一层类加载器表明,他不能加载这个类时,直属的类加载器才会自己加载这个类。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章