类加载机制和类加载器

jvm之java类加载机制和类加载器(ClassLoader)的详解

目录

类加载过程

类的加载时机

类加载器

全盘负责委托机制


类加载过程

类的生命周期:

类加载机制和类加载器_第1张图片

类的加载过程:虚拟机把描述类的数据从class文件加载到内存中,并通过验证、准备、解析和初始化之后,最终形成JVM可以直接使用的Java对象。

类加载机制和类加载器_第2张图片

  • 加载

将类的class文件读入到内存中,并为之创建一个class对象。当程序使用任何类的时候,系统都会为其创建一个class对象。加载工作通过类加载器来完成。

通过使用不同的类加载器,可以从不同来源加载类的二进制数据,通常有以下几种来源:

  1. 从本地文件系统中加载class文件
  2. 从JAR、WAR包加载class文件
  3. 通过网络加载class文件,例如applet
  4. 把一个Java源文件动态编译,并进行加载
  • 验证

确保class文件的字节流中包含的信息符合虚拟机的要求,并且不会危害虚拟机自身的安全。主要包括:文件格式校验;元数据校验;字节码校验;符号引用校验。

  1. 文件格式校验:字节流是否符合class文件格式规范,并且能被当前虚拟机加载处理
  2. 元数据校验:对字节码描述的信息进行分析,是否符合java语言语法规范
  3. 字节码校验:分析数据流和控制,确定语义是否合法,符合逻辑。保证类的方法在运行时不会有危害出现
  4. 符号引用校验:保证引用一定会被访问到,不会出现类等无法访问的问题。
  • 准备

为类的静态变量分配内存,并设置默认初始值。如果是静态常量就设置为表达式所定义的值,而不是默认初始值。a=0;

  • 解析

将类的二进制数据中的符号引用替换成直接引用。

符号引用:符号引用是以一组符号来描述所引用的目标,符号引用可以是任何字面形式的字面量,只要不会冲突能够定位到就行,布局和内存无关。

直接引用:是指向目标的指针,偏移量或者能够直接定位的句柄,该引用和内存布局有关,并且一定被加载进来的。

  • 初始化

为静态变量赋予正确的初始值。a=10;

类的加载时机

  1. 创建类的实例,也就是new一个对象的时候
  2. 访问某个类或接口的静态变量,或者对该静态变量赋值
  3. 调用类的静态方法
  4. 当要使用类的class对象进行反射调用的时候
  5. 当初始化一个类的时候,其父类没有初始化,先初始化这个父类
  6. 启动虚拟机的时候,用户需要指定一个要执行的主类(main()方法所在的类),虚拟机会先初始化这个类

以下情况不会初始化:

  1. 通过子类引用父类的静态字段,子类不会初始化
  2. 通过数组定义来引用类,此类不会初始化

类加载器

两个类相等:需要类本身相等,并且使用同一个类加载器进行加载。类用其类加载器和类全限定名作为类的唯一标识。

应用程序启动时,先把基础类一次性加载到JVM中,其它类等到JVM用到的时候再加载,节省内存空间。

类加载器分类:

  1. 启动类加载器(Bootstrp loader):使用C++实现,是虚拟机自身的一部分。jre/lib,Xbootclasspath,jre/classes中的类。负责装载JRE的核心类库
  2. 扩展类加载器(ExtClassLoader  ):jre/lib/ext,ava.ext.dirs系统变量中的类。负责装载JRE扩展目录ext下的jar类包
  3. 应用程序类加载器(AppClassLoader ):classpath下的类。默认使用应用程序类加载器加载应用程序的类。

类加载机制和类加载器_第3张图片

全盘负责委托机制

  • 全盘负责:当一个当一个ClassLoder装载一个类时,除非显示的使用另一个ClassLoder,该类所依赖及引用的类也由这个ClassLoder载入。
  • 委托机制:是指先委托父类加载器寻找目标,在父类找不到的情况下才在自己的类路径中查找并装载目标类。

安全考虑:创建基础类Integer,并加载,会引起严重后果

使用双亲委派的原因:避免重复加载;安全(例子基础类Integer)

自定义类加载器:继承ClassLoader,重写findclass方法

你可能感兴趣的:(类加载机制和类加载器)