虚拟机类加载机制

参考资料:深入理解Java虚拟机第七章。
一个Java源码如何编译解析然后被加载到虚拟机上运行的?,在彻底搞清楚这个问题之前首先问三个问题,类加载时期是什么时候?类加载的过程是什么?以及类加载究竟是什么?要想知道答案请看下面的介绍。
1、什么是虚拟机的类加载机制?
我们知道一个java源文件通过javac编译成字节码的class文件(通过这个文件中的数据格式可以分辨魔数、版本号、常量等)之后通过虚拟机加载到内存,并对数据进行校验、转换解析和初始化,最终可以被虚拟机直接使用,这就是虚拟机的类加载机制。
2、类加载(初始化)的时机?
首先介绍一下类的生命周期周期,它包括了加载、连接(验证、准备、解析)、初始化、使用、卸载。其中加载、验证、准备、初始化、卸载这五个阶段的顺序是确定的,即类加载必须按照这个顺序按部就班的开始(但可以交叉混合式的进行),但解析却不一定,这是为了支持Java中的动态绑定。
Java虚拟机并没有强制约束加载在什么时候运行,但对于初始化阶段,虚拟机规范了类的4中情况必须立即对类进行初始化:
1)遇到new、getstatic、putstaic或invokestatic这4条字节码指令。即使用new关键字实例化对象的时候,读取或者设置一个类的静态字段(已经放入常量池的除外),以及调用一个类的静态方法的时候。
2)使用java.lang.reflect包的方法的对类进行发射调用的时候。
3)当初始化一个类,发现其父类还没有进行初始化,需要先对父类初始化。(接口可以在需要使用的时候初始化,这也是和类初始化唯一的区别)
4)虚拟机启动,需要运行main()方法的哪个类,会先初始化。
上面4种情况称之为对类的主动引用,除此之外所有引用类的方式,都不会触发初始化,称为被动引用。例如:
1)通过子类引用父类的静态字段
2) 通过数组定义来引用类
3)引用处于常量池的常量。即被final修饰的静态字段
3、类加载过程详解
3.1 首先是加载
1、通过类的全限定名获取此类的二进制流
2、将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构。
3、在Java堆中生成一个此类的对象,作为方法区这些数据的访问入口。
3.2 其次验证过程:文件格式验证、元数据验证、字节码验证和符号引用验证。来保证Java的安全性
3.3 然后准备阶段:正式为类变量分配内存并设置类变量初始值,这些内存大偶在方法区中进行分配。进行内存分配的仅包括类变量(被static修饰的变量),不包括实例变量,实例变量在对象实例化时随着对象一起分配在Java堆中。
3.4 解析阶段:这是虚拟机将常量池内的符号引用替换为直接引用的过程,这个过程包括类或者接口的解析,字段解析,类方法解析、接口方法解析,这些都需要从class_index相中索引的方法所属的类或接口的符号引用。
3.5 初始化:类初始化是类加载过程的最后一步,准备阶段变量已经给了系统的初始值,这里是根据程序自动设置的变量去初始化,初始化阶段是执行类构造器()方法的过程。
4、类加载器
java有两中类加载器:一中是启动类加载器(bootstrap classloader),这个类加载器使用c++语言实现,是虚拟机的一部分,另外一种就是所有其他类加载器,这些都是由Java语言实现,独立于虚拟机外,继承自抽象类java.lang.Classloader.
更加细分可以这样看:
4.1 启动类加载器,负责将bin目录中并且由虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被java程序直接引用。
4.2 扩展类加载器: 负责加载bin/ext目录中,被java.ext.dirs系统变量所指定的中所指定的所有类库,开发者可以直接使用扩展类加载器。
4.3应用程序类加载器,是classLoader中的getSystemClassLoader()方法的返回值,负责加载用户类路径(classpath)上所指定的类库。
这里又派生了类加载器双亲委派模型概念:顶层为启动类加载器,三种类加载器相互配合。
它的工作流程是:一个类加载器收到了类加载的请求,首先将请求交给父类加载器去完成,只有当父类无法完成时子类才去完成。这样的好处是无论什么请求都会传到顶层启动类加载器加载,系统中不会出现多个不同的object类,这对Java程序的稳定运作很重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值