Java中的类加载机制主要有类加载器完成。类加载器可以说是Java语言的一项创新,也是Java语言流行的重要原因之一,称为了Java体系中一块重要的基石。
类与类加载器
类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器都拥有一个独立的类名称空间。也就是说,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
双亲委派模型
从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种的启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部都继承自抽象类java.lang.ClassLoader.
从Java开发人员的角度来看,类加载器还可以划分的更加细致一些,绝大部分Java程序都会使用到以下3种系统提供的类加载器
(1)启动类加载器(Bootstrap ClassLoader)
这个类加载器负责将存放在\lib目录中的,或者被-Xbootclasspath参数所指定的路径中,并且是被虚拟机识别的类库加载到虚拟机内存中。
启动类加载器无法被Java程序直接引用。
(2)扩展类加载器(Extension ClassLoader)
这个类加载器有sun.misc.Launcher$ExtClassLoader实现,它负责加载\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发这可以直接使用扩展类加载器。
(3)应用程序类加载器(Application ClassLoader)
这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。
它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用者个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这3种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图所示。
这种层次关系称为类加载器的双亲委派模型(Parents Delegation Model)。
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不会以继承的关系来实现,二是都使用组合关系来复用父加载器的代码。
双亲委派模型的工作过程是:如果一个类加载器手到了类加载的请求,它首先不会自己去尝试加载这个类,二是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的类加载请求最终都应用传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。
例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将变得一片混乱。
双亲委派模型对于保证Java程序的稳定运行很重要,但它的实现却非常简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法中。
源码如下:先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载器加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。
类与类加载器
类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器都拥有一个独立的类名称空间。也就是说,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
双亲委派模型
从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种的启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部都继承自抽象类java.lang.ClassLoader.
从Java开发人员的角度来看,类加载器还可以划分的更加细致一些,绝大部分Java程序都会使用到以下3种系统提供的类加载器
(1)启动类加载器(Bootstrap ClassLoader)
这个类加载器负责将存放在\lib目录中的,或者被-Xbootclasspath参数所指定的路径中,并且是被虚拟机识别的类库加载到虚拟机内存中。
启动类加载器无法被Java程序直接引用。
(2)扩展类加载器(Extension ClassLoader)
这个类加载器有sun.misc.Launcher$ExtClassLoader实现,它负责加载\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发这可以直接使用扩展类加载器。
(3)应用程序类加载器(Application ClassLoader)
这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。
它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用者个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这3种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图所示。
这种层次关系称为类加载器的双亲委派模型(Parents Delegation Model)。
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不会以继承的关系来实现,二是都使用组合关系来复用父加载器的代码。
双亲委派模型的工作过程是:如果一个类加载器手到了类加载的请求,它首先不会自己去尝试加载这个类,二是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的类加载请求最终都应用传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。
例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将变得一片混乱。
双亲委派模型对于保证Java程序的稳定运行很重要,但它的实现却非常简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法中。
源码如下:先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载器加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }
发表评论
-
fastjson合并两个JSONArray
2018-08-20 01:10 0网上使用fastjson合并两个JSONArray的实例基本 ... -
通过ClassPathXmlApplicationContext启动spring容器
2018-05-27 00:21 0对于spring初学者如果想了解spring,那么最简单的方 ... -
git reflog结果分析
2018-05-23 23:50 0git reflog命令用于gitlab中查询历史提交记录, ... -
linux内核OOM源码分析
2018-05-12 21:17 1057Out Of Memory(OOM),即内存 ... -
Java map按值排序
2018-04-22 22:59 0本文提供一个排序工具类,用于Java中的map如何按照va ... -
IDEA中Enable Auto-Import如何取消
2018-05-27 17:34 3753在使用idea进行maven项目开发时,有时候修改了pom ... -
自定义RejectedExecutionHandler的实现
2018-03-12 21:07 01.RejectedExecutionHandler的 ... -
mysql悲观锁原理详解
2018-03-02 17:45 1582mysql中的锁概念 mysql ... -
ibatis两种批量删除方式
2018-02-28 16:23 0ibatis批量操作网上可以搜到到很多,但大部分都是根据某个 ... -
Java判断List中是否有重复元素
2018-02-24 16:25 0在日常Java开发过程中,我们会去判断List集合中是否存 ... -
Gson实现json与map互相转换
2018-02-23 19:04 01.什么是Gson 什么是Gson,我们从其官网上可以看到 ... -
Lambda expressions are not supported at this language level解决方案
2018-02-23 17:21 0Java8正式版本发布后,很多人希望第一时间能够在自己的ma ... -
Java Builder模式的两种实现
2018-02-08 22:06 0前话 在Java开发过程中经常会遇到有多个属性的对象,在构 ... -
linux服务查询jdk版本
2018-05-27 17:27 1731在linux环境下开发java程序的时候,有时候需要了解安 ... -
idea提交svn提示authentication required的解决方法
2017-05-10 10:18 0idea在提交svn项目代码的时候突然提示authenti ... -
Attribute 'singleton' is not allowed to appear in element 'bean' 解决方案
2017-05-05 17:00 01. 问题描述 在spring应用部署过程中抛出如下异常: ... -
python学习
2016-12-13 15:34 0函数介绍 函数 描述 cmp(x,y) ... -
java Date.setTime时间设置逆流
2017-05-05 16:42 1933业务开发过程中需要对java.util.Da ... -
maven包冲突(java.lang.NoSuchMethodError)解决
2017-02-09 11:04 7295在Java项目开发时一般会使用maven作为项目jar包依 ... -
JavaScript美术馆实例
2016-09-16 19:31 0前言 利用JavaScript和DOM去建立一个图片库, ...
相关推荐
NULL 博文链接:https://278672937.iteye.com/blog/2146869
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。...
Java学习教程-java中number类浅析.docx
浅析Java异常处理机制.pdf
Java内存分析
异常处理是Java语言的重要机制,正确、合理地处理异常对系统的健壮性和稳定性提供了强有力的支持。异常的处理主要包括捕捉异常、程序流程的跳转和异常处理语句块的定义等。
声音技术浅析.doc
JAVA中的IOCP浅析
JAVA 的多线程浅析.pdf和 实用的 分析工具
Java多态性浅析.pdf
Java 观察者模式的浅析 简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者...
Qt事件机制浅析
基于Java的Web开发技术浅析
以《JAVA课程设计》浅析计算机程序设计类课程设计教学模式.pdf
Java语言中This关键字应用浅析,看完后帮助于JAVA中类的操作。
H5 缓存机制浅析 - 移动端 Web 加载性能优化
设计模式论文浅析,对设计模式的起源,分类等进行了系统的描述