美文网首页
三、JAVA类加载器

三、JAVA类加载器

作者: lianzf | 来源:发表于2020-02-21 20:03 被阅读0次

类加载器

通过类的全限定名来获取描述此类的二进制字节流,把类加载阶段中的这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取需要的类,实现这个动作的代码模块称为“类加载器”。

public abstract class ClassLoader {
    // 父加载器
    private final ClassLoader parent;
    // 加载类的核心方法之一。如果没找到类则抛出ClassNotFoundException
    protected Class loadClass(Stringname, boolean resolve)throws ClassNotFoundException{
        // synchronized意味着:
        // 1. 同一时间只允许一个线程加载名字为name的类
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has alreadybeen loaded
            // 2. 在加载之前先检查,是否已经加载过该类
            Class c = findLoadedClass(name);
            // 3. c==null代表只有没有被加载过的类才会进行加载
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    // 双亲委派
                    // 父加载器能加载的绝不给子类加载
                    if (parent != null) {
                        // 如果父加载器不为null,则把类加载的工作交给父加载器
                        c = parent.loadClass(name, false);
                    } else {
                        // 如果父加载器为null,则把类加载的工作交给BootstrapClassLoader
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if classnot found
                    // from the non-null parent class loader
                }
                // 如果父加载器不能加载,子加载器去尝试加载
                if (c == null) {
                    // If still not found, then invokefindClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    // 子加载器去尝试加载
                    c = findClass(name);
                    // this is the defining class loader;record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1- t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
}

ClassLoader.loadClass核心代码总结:

同一时间只允许一个线程加载名字为name的类。
在加载之前先检查,是否已经加载过该类。只有没有加载过的才允许加载
双亲委派:父加载器能加载的绝不给子类加载
父加载器加载不到类的情况,交给子加载器去加载(即:findClass)

虚拟机类加载器

从Java虚拟机角度来讲,只存在两种不同的类加载器:一种是启动类加载器(BootstrapClassLoader),由C++语言实现,是虚拟机自身的一部分;另一种是所有其他的类加载器,由Java语言实现,独立于虚拟机外部,全部继承抽象类java.lang.ClassLoader。

从开发人员角度来看,类加载器大致分一下三种:

启动类加载器(BootstrapClassLoader):负责将存放在\lib目录中的,或被-Xbootclasspath参数指定的路径中的,并且是虚拟机识别的类库加载到虚拟机中。如,rt.jar。名字不符合即使放在目录中也不被加载。如果需要把加载请求委派给引导类加载器,直接使用null代替即可。
扩展类加载器(ExtensionClassLoader):由sum.misc.Launcher$ExtClassLoader实现,负责加载<Java_Home>\lib\ext目录中的,或者被java.ext.dir系统变量所指定的路径中的所有类库。开发者可以直接使用扩展类加载器。
应用程序类加载器(ApplicationClassLoader):由sun.misc.Launcher$App-ClassLoader实现。是ClassLoader中的getSystemClassLoader()方法的返回值,所以也称为系统类加载器。负责加载用户路径(ClassPath)上所指定的类库,如果应用程序中没有自定义过自己的类加载器,这个就是默认的加载器,开发人员可以直接使用这个类加载器。

自定义类加载器

自定义加载器有何用途:

》加密

Java代码很容易被反编译,如果你需要对你的代码进行加密以防止反编译,则可以将编译后的代码用加密算法加密。但加密后的类就不能再使用Java默认的类加载器进行加载,这时候就需要自定义类加载器。

》非标准的来源加载代码

字节码是放在数据库或者网络位置,需要自定义类加载器

双亲委派

什么是双亲委派

如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,因此所有的类加载请求最终都会传送到顶端的启动类加载器;
只有当父加载器在其搜索范围内无法找到所需的类,并将该结果反馈给子加载器,子加载器会尝试去自己加载。

总结:父加载器能加载的绝不给子加载器加载,只有父加载器找不到所需的类才让子加载器尝试加载。

如何打断默认双亲委派机制

如果想打破双亲委派模型,只需要重写loadClass方法即可。

为什么使用双亲委派

对任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。
判断两个类是否"相等",必须是在这两个类被同一个类加载器加载的前提下。

基于双亲委派模型设计,那么Java中基础类,如Object类重复多次的问题就不会存在了,因为经过层层传递,加载请求最终都会被BootstrapClassLoader所响应。加载的Object类也会只有一个,否则如果用户自己编写了一个java.lang.Object类,并把它放到了ClassPath中,会出现很多个Object类,这样Java类型体系中最最基础的行为都无法保证,应用程序也将一片混乱。

相关文章

  • java类加载器及其原理

    java类加载器 : java中默认有三种类加载器:引导类加载器,扩展类加载器,系统类加载器(也叫应用类加载器) ...

  • 类加载的原理

    Java类加载器 类加载器可以分为三类: 启动类加载器(Bootstrap ClassLoader):负责加载\l...

  • 创建一个java.lang.Test类,能被加载吗?

    java中类加载器有三种: Bootstrap类加载器 负责加载java的核心类包,比如rt.jar 拓展类加载...

  • JAVA类加载器

    JAVA类加载器有三大类 BootstarpClassLoder是顶级类加载器,默认加载%JAVA_HOME%中l...

  • JVM类加载相关笔记

    Java类加载器 虚拟机自带的类加载器 启动类加载器(Bootstrap)C++加载Java的核心类($JAVA_...

  • java中的ClassLoader

    java类加载流程 java jvm系统自带三个类加载 BootStrap ClassLoader最顶层的类加载器...

  • Java类加载器 java面试那些jvm的鬼

    Java类加载器 类加载器(class loader) 用来加载 Java 类到 Java 虚拟机中。Java 源...

  • Java类加载机制

    Java类加载过程 Java虚拟机规范Java类加载器 一般我们把Java的类加载分为三个过程: 加载、连接、初始...

  • 类加载器,自定义类加载器

    参考:一篇文章读懂Java类加载器全面解析Java类加载器 类加载器 类加载器结构: ClassLoader类是一...

  • Springboot Application 集成 OSGI 框

    Java 类加载器 启动类加载器 (Bootstrap ClassLoader) 是 Java 类加载层次中最顶层...

网友评论

      本文标题:三、JAVA类加载器

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