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

java类的生命周期4类加载的父亲委托机制

2017-11-28 08:34 246 查看
                                                              类加载的父亲委托机制
   在父亲委托机制中,各个加载器按照父子关系形成了树形结构,除了根类加载器,其他的类加载器有且只有一个父加载器。假如loader2的父亲为loader1,loader1的父亲是系统类加载器。假设Java程序要求loader2加载Sample类,代码如下:
     Class sampleClass = loader2.loadClass("Sample");
   loader2首先从自己的命名空间中查找Sample类是否已经被加载,如果已经被加载,直接返回代表Sample类的Class对象的引用
   如果Sample类还没有被加载,loader2首先请求loader1代为加载,loader1在请求系统类加载器代为加载,系统类加载器再请求扩展类加载器代为加载,扩展类加载器再请求根类加载器代为加载。若根类加载器和扩展类加载器都不能加载,则系统类加载器代为加载,若能加载成功,则将Sample类所对应的Class对象的引用返回给loader1,loader1再将引用返回给loader2,从而成功将Sample类加载进虚拟机。若系统类加载器不能加载Sample类,则loader1尝试加载Sample类,若loader1不能加载,则loader2尝试加载。若所有的父加载器及loader2不能成功加载,则跑出ClassNotFoundException异常
   若有一个类加载器能成功Sample类,那么这个类加载器就被称为定义类加载器,所有能成功返回Class对象的引用的类加载器(包括定义类加载器)都被称为初始类加载器。假设loader1实际加载了Sample类,则loader1为Sample类的定义类加载器,loader1和loader2为Sample类的初始类加载器
   需要指出的是,加载器之间的父子关系实际上指的是加载器之间的包装关系,而不是类之间的继承关系。一对父子加载器可能是同一个加载器类的两个实例,也可能不是。例如下面的loader1和loader2都是MyClassLoader类的实例,并且loader2包装了loader1,loader1是loader2的父加载器.
   ClassLoader loader1 = new MyClassLoader();
    //参数loader1将作为loader2的父加载器
   ClassLoader loader2 = new MyClassLoader(loader1);
   父亲委托机制的优点是能够提高软件系统的安全性,因为在此机制下,用户自定义的类加载器不可能加载应该由父加载器加载的可靠类,从而防止不可靠甚至恶意的代码代替父加载器加载的可靠代码。例如,java.lang.Object类总是由根类加载器加载,其他任何用户自定义的类加载器都不可能加载含有恶意的java.lang.Object类
1.命名空间
每个类加载器都有自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成.在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类;在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类
在同一个命名空间中,允许出现类名相同,但是包名不同的两个类,像org.sbc.Sample和com.abc.Sample
2.运行时包
由同一个类加载器加载的属于相同包的类组成了运行时包。决定两个类是不是属于同一个运行时包,不仅要看他们的包名是否相同,还要看定义类加载器是否相同。只有属于同一运行包的类才可以互相访问包可见(即默认访问级别)的类和类成员。这样的限制能避免用户自己定义了一个类java.lang.SPY,并由用户自定义的加载器去加载,由于java.lang.SPY和java.lang.*由不同的加载器加载,他们属于不同的运行时包,所以java.lang.SPY不能访问核心类库java.lang包中的包可见成员
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: