2015.6.24(ClassLoader)

今天学习了ClassLoader机制。
当我们写好一个Java程序之后,不管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以要经常从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的话,则会引发系统异常。而程序在启动的时候,并不会一次性加载程序所有的class文件,而是根据需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,只有当class文件被载入到了内存之后,才能被其它class所引用,ClassLoader就是用来动态加载class文件到内存当中去的。
1. Java默认提供三个ClassLoader:
1) BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等,可通过System.out.println(System.getProperty(“sun.boot.class.path”))获得BootStrap ClassLoader类加载器从哪些地方加载了相关的jar或class文件。
2) Extension ClassLoader:称为扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包。
3) System ClassLoader:称为系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件。
4) 除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,包括Java提供的另外两个ClassLoader(Extension ClassLoader和System ClassLoader)都继承自java.lang.ClassLoader。但是Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,底层由C++编写,嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和System ClassLoader类加载器。
2. ClassLoader启动顺序:
先加载Bootstrap Classloader,然后是Extension Classloader,最后才是System Classloader,加载的Class越重要的越靠前。这样做是出于安全性的考虑,试想如果System Classloader“亲自”加载了一个自定义的“java.lang.System”类,如何来保证该类在程序中执行的安全性和冲突。这种委托机制保证了用户即使具有一个“java.lang.Systme”这样的类,也把它加入到了类路径中,但是它永远不会被载入,因为这个类总是由Bootstrap Classloader来加载的。
3. ClassLoader加载原理:
双亲委托模型:ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,如果自己搜不到这个类,就把任务委托给它的父类加载器,这个过程是由下至上依次检查的,如果它的父类Extension ClassLoader和Bootstrap ClassLoader都没有加载到这个类,则抛出ClassNotFoundException异常,否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象供应用程序调用。

  1. 应用举例——如何在程序运行时用自定义ClassLoader动态的加载Class(一般都是继承了基类或者接口的子类):
    我们用自定义的ClassLoader来动态载入Class的时候,发现它有一个父类Class,在载入它之前JVM先会载入其父类Class,其父类Class根据委托机制,将由System Classloader载入,然后我们自定义的ClassLoader再载入这个Class,创建一个实例,造型为其父类Class,造型成父类 Class(也就是上溯)是面向对象的java语言所允许的并且也是JVM所支持的,JVM就使用System Classloader再次载入这个父类Class。我们可以从这个过程发现两次加载的这个父类Class都是由System Classloader完成的,也就是同一个ClassLoader载入的同一个父类Class,所以造型的时候不会出现任何异常。而根据多形性,调用这个父类的方法时,真正执行的是这个Class(非父类 Class)的方法。
    这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中,然后在执行的时候动态的载入实现或者继承了接口或基类的子类。例如Servlet,Web Application Server能够载入任何继承了Servlet的Class并正确的执行它们,不管它实际的Class是什么,把它们都实例化成为一个Servlet Class,然后执行Servlet的init,doPost,doGet和destroy等方法。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值