「每天一道面试题」如何理解双亲委派模型及为什么要使用这种机制

「每天一道面试题」如何理解双亲委派模型及为什么要使用这种机制_第1张图片

类加载器种类

在理解双亲委派模型之前,先来了解一下类加载器的种类。

从Java虚拟机的角度来说,有两种不同的类加载器:启动类加载器和其它类加载器。启动类加载器在HotSpot虚拟机中使用C++语言实现,它是虚拟机的一部分;除了启动类加载器之外的其它类加载器都由Java语言实现,并且全部继承自java.lang.ClassLoader,它们是独立于虚拟机外部的。

从程序开发人员的角度来说,类加载器分为四类:启动类加载器、扩展类加载器、应用类加载器和自定义类加载器。下面分别介绍这些类加载器。

  • 启动类加载器:它的作用是将JAVA_HOME/lib目录下的类加载到内存中。需要注意的是由于启动类加载器涉及到虚拟机本地的实现细节,开发人员将无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。

  • 扩展类加载器:它是由Sun的ExtClassLoader实现的,它的作用是将JAVA_HOME/lib/ext目录下或由系统变量 java.ext.dir指定位置中的类加载到内存中,它可以由开发人员直接使用。

  • 应用程序类加载器:它是由Sun的AppClassLoader实现的,它的作用是将classpath路径下指定的类加载到内存中。它也可以由开发人员使用。

  • 自定义类加载器:自定义的类加载器继承自ClassLoader,并覆盖findClass方法,它的作用是将特殊用途的类加载到内存中。

双亲委派模型

所谓的类加载器的双亲委派模型指的是类加载器之间的层次关系。该模型要求除了顶层的启动类加载器外,其余的类加载器都应该有自己的父类加载器,而这种父子关系一般通过组合关系来实现,而不是通过继承。下图展示的既是双亲委派模型。

「每天一道面试题」如何理解双亲委派模型及为什么要使用这种机制_第2张图片

某一个类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,则成功返回;如果父类加载器无法完成加载任务,将抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载,依次类推。

双亲委派模型的好处

它的好处可以用一句话总结,即防止内存中出现多份同样的字节码。

从反向思考这个问题,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证,而且如果不使用这种双亲委派模型将会给虚拟机的安全带来隐患。所以,要让类对象进行比较有意义,前提是他们要被同一个类加载器加载。

你可能感兴趣的:(「每天一道面试题」如何理解双亲委派模型及为什么要使用这种机制)