【java】--类加载机制

【前言】

     从类被加载到虚拟机内存中开始,到卸御出内存为止,它的整个生命周期分为7个阶段,加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸御(Unloading)。其中验证、准备、解析三个部分统称为连接。
7个阶段发生的顺序如下:


1. 加载


  • 通过一个类的全限定名来获取定义此类的二进制字节流。
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
  • 注意:JVM中的ClassLoader类加载器加载Class发生在此阶段

注意: JVM中的ClassLoader类加载器加载Class发生着此阶段.

2. 验证

2.1 文件格式的验证


主要验证字节流是否符合Class文件格式的规范,如果符合则把字节流加载到方法区中进行存储。
文件头、主次版本验证等等

2.2 元数据验证

主要对字节码描述的信息进行语义分析,保证其描述符合Java语言的要求。

  • 类是否有父类
  • 是否继承了不允许被继承的类(final修饰过的类)
  • 如果这个类不是抽象类,是否实现其父类或接口中所有要求实现的方法
  • 类中的字段、方法是否与父类产生矛盾(如:覆盖父类final类型的字段,或者不符合个则的方法)

2.3 字节码验证

最复杂的一个阶段。主要目的是通过数据量和控制流分析,确定程序语义是合法的,符合逻辑的。
保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。

2.4 符号引用验证

  • 符号引用中通过字符串描述的全限定名是否能找到对应的类。
  • 在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。
  • 符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问。

3、准备


准备阶段正式为类变量分配内存并设置初始值阶段。public static int value=123; 初始后为 value=0;对于static final类型,在准备阶段会被赋予正确的值public static final value=123;初始化为 value=123;
如果是boolean值默认赋值为:false
如果是对象引用默认赋值为:null
...

注意:
只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是在对象实例化的时候初始化分配值的

4、解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

符号引用:简单的理解就是字符串,比如引用一个类,java.util.ArrayList 这就是一个符号引用,字符串引用的对象不一定被加载。
直接引用:指针或者地址偏移量。引用对象一定在内存(已经加载)。

5、初始化

执行类构造器<clinit>
初始化静态变量、静态块中的数据等(一个类加载器只会初始化一次)
子类的<clinit>调用前保证父类的<clinit>被调用
注意:
<clinit>是线程安全的,执行<clinit>的线程需要先获取锁才能进行初始化操作,保证只有一个线程能执行<clinit>(利用此特性可以实现线程安全的懒汉单例模式)。


什么是类装载器ClassLoader

  • ClassLoader是一个抽象类
  • ClassLoader的实例将读入Java字节码将类装载到JVM中
  • ClassLoader可以定制,满足不同的字节码流获取方式
  • ClassLoader负责类装载过程中的加载阶段。
JVM中的类加载器

  • 启动类加载器(BootStrap ClassLoader):引导类装入器是用本地代码实现的类装入器,它负责将 jdk中jre/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  • 扩展类加载器(Extension ClassLoader):扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将jdk中jre/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  • 系统类加载器(System ClassLoader):系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。
双亲委派模型
    下图中展示了类加载器直接的关系和双亲委派模型
     

  

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值