您的位置:首页 > 编程语言 > Java开发

java ClassLoader 详解

2015-08-07 00:06 375 查看
1.什么是类加载器?

类加载器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件。

类装在工作有ClassLoader及其子类负责,ClassLoader是一个重要的java运行时系统组件,它负责运行时查找和装入class字节码文件。

jvm运行时产生三个ClassLoader:

BootStrap ClassLoader:由C++编写,非ClassLoader子类,在java中看不到;根装载器主要负责JRE的核心类库,lib下的 rt.jar、resources.jar、charset.jar。 

         Ext ClassLoader:扩展类加载器,负责加载JRE扩展目录ext中的JAR类包,主要用来实现第三方的扩展功能。

         App ClassLoader:负责装载ClassPath下的类包。

三个类加载器间的关系可以通过下图形象的描述:  


  

2.类的加载过程

JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示:



1) 装载:查找和导入Class文件;

2)链接:执行验证、准备和解析步骤

a) 验证:确保Class文件被加载类的正确性;

b) 准备:为类的静态变量分配内存,并将其初始化为默认值;

c) 解析:把类中的符号引用转换为直接引用;

3)初始化:为类的静态变量赋予正确的初始值;

          那为什么我要有验证这一步骤呢?首先如果由编译器生成的class文件,它肯定是符合JVM字节码格式的,但是万一有高手自己写一个class文件,让JVM加载并运行,用于恶意用途,就不妙了,因此这个class文件要先过验证这一关,不符合的话不会让它继续执行的,也是为了安全考虑吧。

        准备阶段和初始化阶段看似有点矛盾,其实是不矛盾的,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。

3. 类的初始化  

注:来自 http://blog.csdn.net/gjanyanlig/article/details/6818655   

类什么时候才被初始化:

1)创建类的实例,也就是new一个对象

2)访问某个类或接口的静态变量,或者对该静态变量赋值

3)调用类的静态方法

4)反射(Class.forName("com.lyj.load"))

5)初始化一个类的子类(会首先初始化子类的父类)

6)JVM启动时标明的启动类,即文件名和类名相同的那个类

         只有这6中情况才会导致类的类的初始化。

     类的初始化步骤:

        1)如果这个类还没有被加载和链接,那先进行加载和链接

        2)假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口)

         3)加入类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句。

4.双亲委托机制

下图是ClassLoader的加载类流程图,以加载一个类的过程类示例说明整个ClassLoader的过程。



Java中ClassLoader的加载采用了“双亲委托机制(全盘负责委托机制)”。

   双亲委托机制:某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

 
  好处:java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。双亲委托机制保证了类永远是从根装载器来装载。

java开发,都遇到过java.lang.NoSuchMethodError错误,究其原因就是有JVM的“双亲委托机制”引发的,因为在java的类路径下放了不同版本的类包,如
commons-lang2.x.jar和commons-lang3.x.jar都在类路径中,代码中使用到了common-lang3.x.jar类的某个方法,而这个方法在commons-lang2.x.jar中不存在,jvm加载时碰巧又从commons-lang2.x.jar中加载类,运行时就会抛出NoSuchMethodError错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java bootstrap classloader