JVM加载类的原理

如何加载class文件:

1.利用类加载器将将class文件读入到内存中,并且为这个class文件创建一个实例对象(java.lang.class),如果这个类已经被加载过了,就不会再被加载(同一个类的唯一标识:包名+类名)。

2.将类加载完之后,就是进行连接操作。

3.对类进行初始化。

接下来谈谈各个步骤的详细内容:

一.类的加载

利用不同的加载器,对不同来源的class文件进行加载,class文件有以下来源:

1,我们打好的jar包

2.   网络上的class文件

3.从本地文件系统加载的class

类加载器:

根类加载器(bootstrap classLoader):它的底层是采用c++代码写的,它其实不是classLoader的子类,它也没有子类,

因此它其实是不属于类的加载层级结构的,它完全由jvm来控制的,它负责加载的是java的核心库,比如说String,system这些核心库类。

扩展类加载器(extension classLoader):它负责加载的是jre的扩展目录(java.ext.dirs下的jar包),比如说咱们自己打的jar包。

应用类加载器(system ClassLoader):它负责加载java命令的-classpath选项和java.class.path系统的属性,它的父类是extentionclassLoader。

而extention classLoader和systemclassLoader都是继承了urlclassloader,urlclassloader的父类是classLoader,

因此层级关系大概如下:

用户类加载器->系统类加载器->扩展类加载器

jvm加载类的机制主要是如下几种:

(1)全盘负责:当一个类加载器加载某个class时,还会去加载它所依赖和引用的class,这些被依赖和引用的class文件其实就是隐式加载的方式。而主动加载的某个class是显示加载的方式。

(2)父类委托:先让父类加载器尝试加载此class文件,如果父类无法加载此class文件,则由当前类加载器去加载此clas文件。

(3)缓存机制:先从缓存区读取是否存在该class,如果没有,则利用加载器将其加载成class对象,然后存到缓存区中。

因此加载类的过程如下:

1.先在缓存区取class对象,如果不存在,则会递归请求父类加载器加载此class(用户类加载器->系统类加载器->扩展类加载器),如果父类加载器无法加载此class,则向下递归利用子类加载器加载此class,直到当前类加载器无法加载到class,抛出classnotfindexception,否则返回java.lang.class对象。

二.类的连接

1.验证:检查被加载的类是否有正确的内部结构,

2.准备:类加载器阶段负责对类的类变量分配内存,并且设置默认初始值

3.解析,将类的二进制数据的符号引用转化成直接引用。

三.类的初始化

初始化一个类时,假如直接父类没有初始化,则先初始化其直接父类,,假如类中有初始化语句,则先执行这些初始化语句,

因此类代码的执行顺序大概是这样子的

父类的静态代码块->子类的静态代码块->父类的初始化代码块(在创建对象时隐式执行,且在构造器前执行)->父类的构造函数->子类初始化代码块->子类构造函数

因此每次最先执行顶级的java.lang.object,jvm会保证这个类的所有父类被初始化(包括直接父类和间接父类)

 

 

 

 

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