JVM-虚拟机类加载机制

JVM-虚拟机类加载机制

  • Demo
  • 类与类加载器
  • 双亲委派模型
    • 加载过程
    • 双亲委派机制的作用

学而不思则罔,思而不学则殆

Demo

Demo

类与类加载器

类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类的加载阶段。
对于任意一个类,都需要由加载他的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。通俗一点:比较两个类“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使两个类来源于同一Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那这两个类就必定不相等。
比如

    private static void testDiyClassLoader003() {
        DiyClassLoader003 cl1 = new DiyClassLoader003();
        try {
            Class aClass = cl1.loadClass("Person");
            testClassLoader(aClass);
            Object object = aClass.newInstance();
            show(object.toString());
            show("object instanceof Person = " + (object instanceof Person));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
------------------------------------testClassLoader start
class com.bean.Person
com.jvm.DiyClassLoader003@74a14482
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@677327b6
------------------------------------testClassLoader end
Main--: com.bean.Person@14ae5a5
Main--: object instanceof Person = false

可以看到通过instanceof 判断得到的结果是false,说明虽然都是Person,但是类加载器不一样,所以instanceof 判断不成立

双亲委派模型

从Java虚拟机的角度来讲,只存在两种不同的类加载器:

  1. 一种是启动类加载器,由C++语言实现(HotSpot),
  2. 另一种就是其他的类加载器,是Java语言实现,独立于虚拟机外部,并且全部继承自抽象类java.long.ClassLoader
------------------------------------testClassLoader start
class com.bean.Person
com.jvm.DiyClassLoader003@74a14482 //自定义类加载器
sun.misc.Launcher$AppClassLoader@18b4aac2 //应用程序类加载器
sun.misc.Launcher$ExtClassLoader@677327b6 //扩展类加载器
------------------------------------testClassLoader end

还可以分为:

分类 加载路径
启动类加载器 (Bootstrap ClassLoader) \lib
扩展类加载器 (Extension ClassLoader) \lib\ext
应用程序类加载器 (Application ClassLoader) 加载classpath上指定的类库
自定义类加载器(User ClassLoader) 加载指定的类库

JVM-虚拟机类加载机制_第1张图片
如图:成为类加载器的双亲委派模型(Parents Delegation Model).要求除了顶层的启动类加载器外,其他类加载器都应当有自己的父类加载器。这里类加载之间的父子关系一般不会一继承的关系实现,而是都以组合关系来复用父加载器。

加载过程

如果一个类收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应当传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载时,子加载器才会尝试自己去加载。

    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name); //1是否已经被加载
            if (c == null) { //2没有被加载
                ...
                try {
                    if (parent != null) { //3父加载器存在
                        c = parent.loadClass(name, false); //4尝试用父加载器加载
                    } else {
                        c = findBootstrapClassOrNull(name); //5父加载器不存在,尝试用启动类加载器加载
                    }
                } catch (ClassNotFoundException e) {
                }

                if (c == null) { //6父加载器都加载失败了或者没有加载成功或者没有被加载
                    c = findClass(name);  //7尝试自己加载
                    ...
                }
            }
            ...
            return c;
        }
    }

双亲委派机制的作用

  1. Java类随着它的类加载器一起具备了一种带有优先级的层次关系
  2. 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
  3. 保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。

你可能感兴趣的:(JVM,Java,java,jvm)