美文网首页
Java 类加载器

Java 类加载器

作者: CodeDuan | 来源:发表于2022-03-02 09:37 被阅读0次

一、概述

上篇文章中概述了类的加载流程,那么类是由什么来加载的呢?毫无疑问就是类加载器,类加载器是Java中很重要的概念,它负责将字节码文件加载到Jvm虚拟机中。在Java中有三大类加载器:启动类加载器,扩展类加载器,应用程序类加载器。

二、启动类加载器

启动类加载器(Bootstrap ClassLoader)是由c/c++语言实现的,是JVM的一部分。
它用来加载Java的核心类库:rt.jar,resources.jar或sun.boot.class.path下的内容。

三、扩展类加载器

扩展类加载器(Extension ClassLoader)是由Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。
派生于ClassLoader类。父类加载器为启动类加载器。
它用来加载Java_HOME/lib/ext中的类,以及 java.ext.dirs系统属性所指定的目录中的类库。

四、应用程序类加载器

应用程序类加载器(AppClassLoader)是由Java语言编写,由sun.misc.Launcher$AppClassLoader实现。
派生于ClassLoader类,父类加载器为扩展类加载器。
复杂加载环境变量中classpath或系统属性java.class.path指定路径下的类库。
应用程序类加载器是程序中默认的类加载器,一般Java应用的类都是由它完成加载。

public class Main {
    public static void main(String[] args) {
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        System.out.println(loader);
        System.out.println(loader.getParent());
    }
}

输出:
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@15db9742

五、双亲委派机制

  1. 如果一个类加载器收到了类加载的请求,他并不会自己去加载,而是把这个请求委托给父类加载器。
  2. 如果父类加载器还存在父类加载器,则进一步向上委托,直到请求达到最顶层的启动类加载器。
  3. 如果父类加载器可以完成类的加载则返回,如果父类加载器无法完成加载任务,子加载器才会尝试自己去加载。这就是双亲委派机制。

举个例子:
假如我在项目目录下创建一个java.lang的包,然后再创建一个String类,代码如下:

package java.lang;

public class String {
    static {
        System.out.println("我是自定义的String");
    }
}

然后我们来使用String:

class Test {
    public static void main(String[] args) {
        java.lang.String str = new java.lang.String();
        System.out.println("Hello");
    }
}

此时运行,这个String到底是哪个String呢?自定义的String还是Java核心库中的String呢?我们运行看下输出:

Hello

控制台只输出了Hello,而我们自定义的String中的静态代码块并没有执行,说明加载的是Java核心库的String。
可以说如果你自己创建了一个和Java库中同名的类,那么你的类永远得不到加载。

在这个例子中,如果Java使用Test的类加载器即应用程序加载器加载String,那么加载的就是我们自定义的String了,但是如果加载了自定义的String,万一你自定义的String有毒咋整?所以这就是为什么会有双亲委派机制。

相关文章

网友评论

      本文标题:Java 类加载器

      本文链接:https://www.haomeiwen.com/subject/pcyjrrtx.html