### jvm的类加载机制-类加载器和双亲委派机制(二)

类与类加载器


对于任何一个类,都需要有加载它的类加载器和这个类本身一通确立其在java虚拟机中的唯一性。每一个类加载器,都需要有一个独立的类名称空间。
更通俗一点的意思是:如果需要比较两个类是否 相等,只有当这两个类都是同一个类加载器加载的前提下,才能进行比较,否则如果加载这两个类的加载器完全不同,则这两个类必定是不一样的。

package com.deem.classload.test;

import java.io.InputStream;

public class ClassLoadTest {

    public static void main(String[] args) throws Exception {
        ClassLoader myClassLoad = new ClassLoader() {
            @Override
            public Class loadClass(String name) throws ClassNotFoundException {

                try {
                    String className = name.substring(name.lastIndexOf(".") + 1) + ".class";
                    InputStream is = getClass().getResourceAsStream(className);
                    if (is == null) {
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);

                } catch (Exception e) {
                    throw new ClassNotFoundException(name);
                }
            }
        };

        Object obj = myClassLoad.loadClass("com.deem.classload.test.ClassLoadTest").newInstance();

        System.out.println(obj.getClass());
        System.out.println(obj instanceof com.deem.classload.test.ClassLoadTest );
    }

}
运行结果为

class com.deem.classload.test.ClassLoadTest
false

从第一个输出结果来看,这个对象确实是类com.deem.classload.test.ClassLoadTest实例化出来的对象
第二句 最比较时,返回 false,这个对象时通过我们自定义的类加载器进行加载的,其实此时虚拟机中存在了两个ClassLoadTest类,一个是系统应用程序自己加载的,另一个则是我们自己定义的类加载器进行加载的,虽然都是同一个Class文件,但是依然是两个独立的类,故而结果是false

类加载器与双亲委派机制


JVM预定义的三种类型类加载器:
  1. 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 /lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  1. 标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  1. 系统(System)类加载器:是由 Sun 的
    AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。

除了以上列举的三种类加载器,还有一种比较特殊的类型 — 线程上下文类加载器。

双亲委派机制描述
### jvm的类加载机制-类加载器和双亲委派机制(二)_第1张图片
image.png
### jvm的类加载机制-类加载器和双亲委派机制(二)_第2张图片
image.png

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

参考
  1. 周志明,深入理解Java虚拟机:JVM高级特性与最佳实践,机械工业出版社
  2. Alexia(minmin)博客,http://www.cnblogs.com/lanxuezaipiao/p/4138511.html
  3. 笨鸟快飞的博客,http://blog.csdn.net/u011080472/article/details/51332866

你可能感兴趣的:(### jvm的类加载机制-类加载器和双亲委派机制(二))