类加载机制

 

Java中类只有被加载进JVM中后才可以运行。程序运行时候,JVM会将编译生成.class文件加载到内存,组织成一个完成的java程序。加载过程由类加载器(ClassLoader和它的子类)完成。类加载器本身也是一个类,实质是把类文件从硬盘读取到内存。

  类加载分为:1)隐式加载:程序new一个对象的时候,隐式的调用类加载器把对应的类加载到虚拟机(2)显式加载:直接调用class.forName()

方法来把所需类加载到虚拟机。

项目程序启动时,只需要把需要的类加载进JVM,其他的类需要的时候再加载。这样可以加快加载速度,节约程序运行时候对内存的开销。Java里面每个类和接口都对应一个.class文件,这些.class文件可以被看做一个个可以被动态加载的单元。当只有部分类被修改时候,只需要重新编译变化的类即可,不需要重新编译所有的文件,这样也加快了编译的速度。

加载的时候,程序运行的基础类完全加载进JVM,其他类需要时候再加载。Java中的类分为三类:系统类,扩展类,自定义类。Bootstrap Loader负责加载系统类(jre/lib/rt.jar的类);ExtClassloader(jar/lib/ext/*.jar) 负责加载扩展类;AppClassloader(classpath指定的目录或jar中类)负责加载应用类。

这三个类加载器是通过双亲委派模型进行协调工作的:类加载的时候,类加载器会先请求父类来加载,父类使用自己的搜索路径搜索这个要加载的类,如果找不到就交给子类,然后子类按照子类自己的搜索路径搜索加载这个类。

比较两个类是否相同,只有这两个类是由同一个类加载器加载的前提下才有意义,否则即使这两个类来源于同一个class文件,被同一个虚拟机加载,只要加载他们的加载器不同,他们就是不同的类。

使用双亲委派模型的好处:Java类因为它的类加载器具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类,可以正常编译,但是永远无法被加载运行。

类从加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:装载-验证-准备-解析-初始化-使用-卸载,其中验证-准备-解析称为链接。

类加载主要分为以下几个步骤:

  1. 装载:查找路径找到对应的class文件,导入
  2. 链接(三步):
  1. 检查:检查导入的class文件是否正确
  2. 准备:给类中静态变量分配存储空间
  3. 解析:将符号引用转换成直接引用

      3)初始化:对静态变量和静态代码块执行初始化工作。

当运行一个程序时,JVM启动,运行bootstrap classloader加载器 ,该加载器加载系统类(包括ExtClassloader 和AppClassloader 也在此时被加载),然后调用ExtClassloader 加载扩展类,最后AppClassloader 加载classpath目录下定义的class或jar中的类,这就是一个程序最基本的加载流程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值