java中的类加载过程.md

加载阶段

类加载包括:加载、验证、准备、解析、初始化这五个小过程

加载:这个阶段JVM主要完成三件事:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流(读取)
  2. 将这个字节流所代表的的静态存储结构转化为方法区运行时数据结构(类信息)
  3. 在内存中生成一个代表这个类的java.lang.class对象,然后就可以根据这个内存中的class对象类创建类的实例。

链接阶段

验证:这一阶段的目的是为了确保class问及那的字节流中包含的信息符合当前JVM的要求
  1. 文件格式验证、元数据验证、字节码验证、符号引用验证

准备

验证通过之后就会执行准备阶段。该阶段主要是为类变量(静态变量)分配内存并设置类变量初始值的阶段,这些变量都存放在方法区中(实例变量都随着对象存放在堆 )比如 
public static int value = 123;public static final int value = 123; 
变量value在准备阶段过后的初始值为0而不是123,这个123是在初始化阶段完成的。 
原因:这个123实际被赋值是因为存放在类构造器(注意与实例构造器),在初始化的时候会调用这个类构造器类将123赋值给value。 是由编译器自动收集类中的所有类变量的赋值动作和静态语句快中的语句合并产生的(详见初始化)。 
但是在增加了final关键字之后这个123就会在准备阶段将其直接赋值为123。在编译是javac会为value生成ConstantValue属性,在准备阶段JVM会根据这个ConstantValue属性将这个值设置为123。

解析:解析阶段是一个修改class文件内容的过程。解析阶段是JVM讲常量池内的符号引用替换为直接引用的过程。在类加载的解析阶段会将一部分的符号引用转化为直接引用。有的是在静态分配的时候转化为直接引用。

    符号引用、直接引用详见符号引用与直接引用。方法在程序真正运行之前就有一个可以确定的版本,这类方法的调用称为解析。在编译期间就完全确定,在类加载的解析阶段就会吧设计的符号引用全部转变为直接引用。不会延迟到运行期再去完成。(当然运行一次之后全部变为直接引用了)

初始化阶段

  初始化阶段是类加载过程的最后一步,这里主要是一个  <clinit()>方法,前面已经说过初始化是真正的给类变量赋值的阶段。

  在准备阶段,变量已经赋过一次系统要求的初始值(0  null……),而在初始化阶段,则根据程序员的需求将变量的值重新赋值为自己想要的值。这里就会调用这个  <clinit()>方法

方法

该方法是由编译器自动收集类中所有的类变量的赋值动作和静态语句块中的语句合并产生的,你可以理解为将类中的所有静态变量与讲静态代码块都整合到一个方法中,但是这里有一个需要注意的地方,那就是整合的顺序。

代码一:

static{ System.out.println("父类静态代码块"); } public static String name = setName(); 
先代码块后静态量

与代码二:

public static String name = setName(); static{ System.out.println("父类静态代码块"); } 
先静态量后代码块 
这两段代码看似没有什么区别,但是在 方法收集静态变量与静态代码快的时候有这顺序上的不同,也就是说 方法收集的时候不是按照类别(比如收集静态量的 
只管收集静态量……),这里如果静态代码快放在了静态量的前面,这个时候的收集顺序就是先收集静态代码块在收集静态量(代码一)。代码二则先收集静态量在收集静态代码块 
。收集的顺序不同执行的顺序也就不同。先收集谁JVM就会先运行谁,这个不是固定的。,但是静态的一定先与非静态的执行。 
存储 
在一个类加载完成后,有关被加载类的 类信息 常量 静态变量 即时编译器编译后的数据都存放在静态存储区,也叫方法区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值