类装载器是装载类字节码的工具.它负责根据一个类的名称来找到相应.class文件,并读取该文件生成字节码数据给Java虚拟机.Java虚拟机解析里面的数据并将它转化为机器码来执行.装载进Java虚拟机的数据都是Unicode编码的,但.class并不是,所以这也是类装载器的职责.
说道类加载器,不得不提一下一个特殊类,Java中有一个类是专门来描述一个 Java类的,Java类可以表示一切事物,但Java类也是一个事物,由谁来表示呢,还是Java类叫Class,可能你会觉得自相矛盾,但其实在计算机领域这是合理的.有没有描述Class类的呢,我想应该没有,也没有意义.Class类能描述一个类所有相关信息.每个类都对应一个Class实例对象,它封装着这个类的字节码数据,类装载器装载某个类的字节码数据的过程实际上就是创建这个类对应的Class实例对象,获得某个类的Class的实例对象有3种方法,分别为:
1.类名.class,例如System.class
2.对象.getClass(),例如new Date().getClass()
3.Class.forName("类名"),例如:Class.forName("java.util.Date");
这些只是后台的东西,我们不用太关心,下面的作为Java程序员就应该知道了.
1.类装载器本身是一个Java类,这个类也是有层次关系的,基类就是Java.lang.ClassLoader,它是个抽象类,所以真正起作用的是它的子类.
2.Class类的实例对象可以调用getClassLoader获取装载它的类装载器,就象儿子都知道自己的爸爸一样.
3.ClassLoader有不同的子类,组成了一个ClassLoader家族,每个成员都有自己的职责.
3.类加载器也是一个类,也需要类加载器加载,最上头的是一个名为"Bootstrap"类加载器,它是由操作系统的本地代码实现的,是Java虚拟机的内核,不需要类加载器加载,所以Java虚拟机由各种操作系统版本之分.Bootstrap加载Java核心包的类,所以这些类的Class实例的getClassLoader返回为Null值.
4.Java核心包里有2个用Java编写的类加载器,分别为ExtClassLoader和AppClassLoader,他们各有自己的职能,Ext负责加载进<Java_Home>/jre/lib/ext目录下的Jar包中的类,App负责加载应用程序的启动执行,也就是ClassPath对应路径下的类
5.每个ClassLoader只能加载特定位置和目录下的类,但是子ClassLoader可以委托它的父级的ClassLoader去加载类,从而利用一个子级的classloader就可以加载ClassLoader家族里所有能加载的类,最低下的类就是AppclassLoader类,
6.一个类加载器对某个类只会创建一份字节码数据,也就是Class实例对象,就好比单态模式一样.虽然Java里有多个类加载器,但都拥有自己的名称空间,这些名称空间没有交集,所以依据一个类的存放位置,这个类只能被加载一次,即使你把一个类存放在2个地方,如果类名一样,它也只会被加载一次,如果起不一样的名称,那么对于Java虚拟机来说,这2个类是不一样的,因为他们的名字不一样.这就像map类型结构一样,只管键值,而不管Value值.
7.如果类A中使用new关键值创建类B,那么虚拟机默认用装载类A的类装载器去加载类B,,这里要注意父级类加载器不会委托子级类加载器去加载类,所以在父级的类加载器名称空间的类不能创建子级类加载器名称空间的类的对象,否则会报ClassNotFoundException异常.