A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 施大勇 中级黑马   /  2013-9-21 13:23  /  1686 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

/**

之前类加载器一直搞的不太明白,在网上又找了高手的分析,仔细学习了半天,还有一些其它东西暂时还真不知道是什么技术,现在把自己认为算是其础的知识点梳理了一下,作为自己在这块的一个总结,同时也希望坛友能在这里共同分析学习,有大神能把难懂的知识用 通俗的话给讲解下就更好了。
* 一:什么是类加载器?
*   一个类要想应用,它应该存在于JVM中,因人我们知道JAVA是通过JVM来处理运算*.class文件的,那么它是如何进入JVM中的呢?这里就需要一个东西将它弄到JVM中,
* 这个将*.class字节码文件弄进JVM中的东西就是类的加载器。
* 二:*.class文件存放在不同的目录下,类加载器是如何将它们弄到JVM中的呢?
*   这里就存在一个问题,类加载器又是如何进入JVM并将想要应用的类加载到JVM中的呢?java已经为我们想好了这样的问题,它提供了三个系统中存在的加载器:
* 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
* 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
* 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。
* 那么系统为什么提供了三个类加载器呢?这时就要分析下JVM是怎样判断两个类是否相同。Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。
* 只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。
* 比如:A.class文件存放在d:\\myclass目录下,有两个类加载器C,D,它们都将A.class文件加载到JVM中并且使用其生成了对象boj1和obj2,那么JVM就认为这两个对象也不
* 是相等的。(不同的类加载器为相同名称的类创建了额外的名称空间。相同名称的类可以并存在 Java 虚拟机中,只需要用不同的类加载器来加载它们即可。
* 不同类加载器加载的类之间是不兼容的,这就相当于在 Java 虚拟机内部创建了一个个相互隔离的 Java 类空间。)这种情况是我们不想要的,所以类加载器采用了代理模式,
* 也就是每一个类都有一个发起加载它的类加载器,但是这个类加载器不会直接加载此类,它将这个任务交给了父类加载器,由父类加载器进行加载,而父类加载器又有父类加
* 载器,那么最终的父类加载器必须有唯一的一个,它是所有加载器的父加载器,这个加载器就是引导类加载器。引导类加载器是由底层代码实现的。
* 系统提供的每个加载器都有它的加载范围,引导类加载器加载JAVA的核心类库,这样就保证了每一个程序加载的核心类库中的类在JVM中是同一个类。
*   具本的类加载过程:
* 如果不自定义类加载器,通常都用的是系统类加载器,它是类加载的发起者,通过代理模式向上查询父类加载器,依此类推向上查询,如果根父类加载器成功加载,则完成加载。
* 如果父类加载器没加载成功,则返回由发起者进行加载,父类加载器都有一个加载目录,它们只在其加载目录下加载,加载目录下没有找到,则返回由它的发起者加载,依此向下推。
*   具体的每个加载器如何进行加载:
* loaderClass()方法启动类加载。它调用findLoaderClass()看是否加载过了,若加载过了则不再加载,使用已加载过的类,若没加载过,则向上发起,它的父加载器依次向上发起
* 查询,若父加载器没加载成功,最后返回最先发起的加载器,它再在它定义好的目录下查询,若查到通过defineClass()方法返回此类对应的Class对象。加载成功。
* */

1 个回复

正序浏览
总结的很好,顶一个,支持你,但有一个地方写得不对:
根类加载器(bootstrap class loader):它用来加载 Java 的核心库,这个类是由jvm自身实现的,并不是ClassLoader的子类,我们在循环打印父类加载器的时候,总是看到扩展类加载器的父类加载器是为null的,这就说明了这一点了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马