带你玩玩类加载器

前言

看大部分博客讲到类加载器时都会讲一堆理论,稍显枯燥,今天我就来带你们玩点好玩的,手动加入拓展类,看看是否是真的是由扩展类加载器所加载?java

类加载器

  • Bootstrap ClassLoader(启动类加载器)负责将%JAVA_HOME%/lib目录中或-Xbootclasspath中参数指定的路径中的,而且是虚拟机识别的(按名称)类库加载到JVM中
  • Extension ClassLoader(扩展类加载器)负责加载%JAVA_HOME%/lib/ext中的全部类库
  • Application ClassLoader(应用程序加载器) 负责ClassPath中的类库,就是用户定义的类

扩展类加载器

package bingo;
public class Bingo {
    public static void main(String[] args) {
        System.out.println("关注J2彬彬");
    }
}
复制代码

ext文件夹就是JDK存放扩展类的地方,将上面这段代码编译成class文件,放到下图的的bingo文件夹下程序员

直接将bingo文件夹打成jar包,执行下图命令,打成jar包后如上图所示产生一个bingo.jar
在IDEA的类路径下能够看到我加入的jar包

下面是个简单的案例后端

package com.bingo.classloader;

import bingo.Bingo;


public class ClassLoaderTest {

    public static void main(String[] args) {

        Object object = new Object();
        System.out.println("object加载器:"+object.getClass().getClassLoader());

        Bingo bingo = new Bingo();
        System.out.println("bingo加载器:"+bingo.getClass().getClassLoader());
        System.out.println("bingo加载器的父类:"+bingo.getClass().getClassLoader().getParent());

        ClassLoaderTest test = new ClassLoaderTest();
        System.out.println("test加载器:"+test.getClass().getClassLoader());
        System.out.println("test加载器的父类:"+test.getClass().getClassLoader().getParent());
        System.out.println("test加载器的父类的父类:"+test.getClass().getClassLoader().getParent().getParent());

    }
}
复制代码

执行结果:微信

object加载器:null
bingo加载器:sun.misc.Launcher$ExtClassLoader@29453f44
bingo加载器的父类:null
test加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
test加载器的父类:sun.misc.Launcher$ExtClassLoader@29453f44
test加载器的父类的父类:null
复制代码

双亲委派模型

由执行结果能够看出,Bingo类由ExtClassLoader加载,用户自定义的类通常都是由AppClassLoader加载,而Object类在rt.jar下,由Bootstrap加载器加载,它是由C++实现的,因此打印结果为null。getParent()获得父类加载器,这里就能够看出双亲委派模型。学习

为何要加载类须要委托双亲加载呢?spa

  • 每个类都只会被加载一次,避免了重复加载
  • 每个类都会被尽量的加载(从引导类加载器往下,每一个加载器均可能会根据优先次序尝试加载它)
  • 有效避免了某些恶意类的加载(好比自定义了Java。lang.Object类,通常而言在双亲委派模型下会加载系统的Object类而不是自定义的Object类)

我是广州的java程序员小彬,一直在致力于java后端的学习,下面是个人微信公众号,里面有更多有质量的文章,感谢你们!3d

相关文章
相关标签/搜索