JVM类加载

JVM类加载机制分为五部分:加载、连接(验证,准备,解析)、初始化;
加载
加载是类加载过程的第一个阶段。在这个阶段JVM将字节码从各个位置(网络磁盘)转换成二进制字节流加载到内存中,接着会为这个类在JVM的方法区创建一个Class对象,是这个类各个数据的访问入口。
连接
注意:连接阶段和加载阶段是交叉进行的
验证:是为了保证class文件的字节流中包含的信息符合虚拟机的要求
准备:这个阶段是正式为类变量分配内存并设置类变量初始值,这些内存都在方法区分配。这个时候进行内存分配的仅仅是类变量(被static修饰的),不包括实例变量,实例变量是在对象初始化时随着对象分配到java堆中。
比如public static int value = 3;变量value在准备阶段过后值为0,而不是3,因为这个阶段尚未开始执行任何java方法,把value赋值为3是在程序编译之后,存放在类构造器中,所以把value赋值为3的动作是在初始化阶段才会执行的
比如public static final value = 3;被static和final修饰的变量称为ConstValue属性。编译时会为value赋值为3,即在准备阶段value的值就为3。
初始化:
这个阶段主要是进行类初始化,是执行类构造器的过程。换句话说,是只对static修饰的变量或语句进行初始化。
如果初始化一个类的时候,其父类还没有初始化,则优先初始化父类,如果同时包含多个静态变量和静态代码块,按照自上而下的顺序依次执行。
<clinit()> 类构造器方法
编译器自动收集类中的所有类变量赋值动作和静态代码块,按在源文件中出现的顺序。注意:静态代码块只能访问到定义在它之前的类变量,定义在它之后的类变量只能赋值不能访问,列如:

public class Test{
	static {
		i = 2;    //编译可以通过               
		System.out.print(i);  //编译器报"非法的前向引用"
	}
	static int i = 1;
}

与类的构造函数(实例构造器<init()>)不同,不需要显示的调用父类构造器,JVM会保证在子类的()构造器执行之前,父类的<clinit()>方法已经执行完毕,因此JVM第一个执行的<clinit()>肯定是java.lang.Object;
由于父类的<clinit()>先执行,意味着父类定义的静态语句块要优先与子类的赋值操作

类加载器的分类:
启动类加载器
扩展类加载器
系统类加载器

双亲委派机制

流程:如果一个类加载器收到类加载的请求,它首先不会自己去请求加载这个类,而是把请求委托给父加载器去完成,依次向上,因此所有的请求都会被传递到顶层的类加载器中,只有当父加载器在他的搜索范围内没有找到所需的类时,子类才会加载该类
优点:可避免重复加载,父类已经加载了,子类就不需要加载了;更加安全,很好的解决了各个类加载器的基础类的统一问题,如果不使用这种方式,用户自定义类加载器来随意加载核心api,会有隐患。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值