JVM类加载笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/JY_He/article/details/88291218

参考博文:https://www.cnblogs.com/jswang/p/7699643.html

                  http://www.importnew.com/25295.html

JVM类加载过程

一个类运行分为以下几步:装载、链接、初始化;

装载:

  1. 通过类的完全限定名,产生一个代表该类型的二进制数据流;
  2. 解析这个二进制数据流为方法区的内部结构;
  3. 构建一个表示该类型的java.lang.Class类的实例

注意:如果一个类装载器在预装载的时遇到错误或缺失class文件,需要等到程序首次主动使用这个类时才会报错。

链接:

  1. 验证:确认类型符合Java语言的语义,检查类的兼容性,以及符合引用的验证;
  2. 准备:为类变量分配内存,设置初始默认值
  3. 解析:符号引用转换成直接引用,其中符号引用以一组符号描述所引用的目标,符号可以任何形式的字面量;直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄,如果有了直接引用,那么引用目标一定已经存在内存中。(类或接口的解析、字段解析、类方法解析和接口方法解析)

初始化:

初始化是类加载的最后一个阶段,到了初始化加载阶段才开始真正执行类中自定义的Java代码程序,执行类构造器<client>方法过程,以下会触发类初始化操作:

  1. 当创建某个类实例(如通过new或者反射、克隆、反序列化等)
  2. 当调用某个类的静态方法
  3. 当使用某个类或接口的静态字段时;
  4. 当通过反射访问某个类的方法时;
  5. 当初始化某个子类;
  6. 当运行启动类(包含main方法的类)

Java编译器会收集所有的变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中client中。

 

其中,static代码块的执行发生在初始化阶段。初始化阶段,jvm主要完成静态变量的初始化,静态代码块的执行

static final关键字修饰的属性:

static修饰,表示该属性属于类,全局只有一个;final修饰的属性表示为常量,一旦初始化无法修改,static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问,在类的加载过程中的准备阶段赋值。

 

类加载器:

JVM 提供了三种类加载器:

  1. 启动类加载器:负责加载JAVA_HOME\lib目录中的,或者通过-Xbootclasspath参数指定路径中的类;
  2. 扩展类加载器:负责加载JAVA_HOME\lib\ext目录中的类库;
  3. 应用程序类加载器:负责加载用户路径classpath上的类库。

JVM通过双亲委派模型进行类加载,也可以继承java.lang.ClassLoader实现自定义的类加载器。

                                  

当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务会传到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试加载任务。

采用双亲加载机制好处:比如加载一个类,不管哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同类加载器最终得到都是同一个Object对象。

 

猜你喜欢

转载自blog.csdn.net/JY_He/article/details/88291218
今日推荐