一、 类加载器

  ClassLoader即常说的类加载器,其功能是用于从Class文件加载所需的类,主要场景用于热部署、代码热替换等场景。

  系统提供3种的类加载器:Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader

  1.1 Bootstrap ClassLoader

  启动类加载器,一般由C++实现,是虚拟机的一部分。该类加载器主要职责是将JAVA_HOME路径下的\lib目录中能被虚拟机识别的类库(比如rt.jar)加载到虚拟机内存中。Java程序无法直接引用该类加载器

  1.2 Extension ClassLoader

  扩展类加载器,由Java实现,独立于虚拟机的外部。该类加载器主要职责将JAVA_HOME路径下的\lib\ext目录中的所有类库,开发者可直接使用扩展类加载器。 该加载器是由sun.misc.Launcher$ExtClassLoader实现。

  1.3 Application ClassLoader

  应用程序类加载器,该加载器是由sun.misc.Launcher$AppClassLoader实现,该类加载器负责加载用户类路径上所指定的类库。开发者可通过ClassLoader.getSystemClassLoader()方法直接获取,故又称为系统类加载器。当应用程序没有自定义类加载器时,默认采用该类加载器。

  ClassLoader.java:

  public static ClassLoader getSystemClassLoader() {

  initSystemClassLoader(); //初始化系统类加载器

  if (scl == null) {

  return null;

  }

  SecurityManager sm = System.getSecurityManager();

  if (sm != null) {

  ClassLoader ccl = getCallerClassLoader();

  if (ccl != null ccl != scl !scl.isAncestor(ccl)) {

  sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);

  }

  }

  return scl;

  }

  系统类加载器初始化:

  private static synchronized void initSystemClassLoader() {

  if (!sclSet) {

  if (scl != null)

  throw new IllegalStateException(recursive invocation);

  sun.misc.Launcher l = sun.misc.Launcher.getLauncher();

  if (l != null) {

  Throwable oops = null;

  scl = l.getClassLoader();

  try {

  scl = AccessController.doPrivileged(

  new SystemClassLoaderAction(scl));

  } catch (PrivilegedActionException pae) {

  oops = pae.getCause();

  if (oops instanceof InvocationTargetException) {

  oops = oops.getCause();

  }

  }

  if (oops != null) {

  if (oops instanceof Error) {

  throw (Error) oops;

  } else {

  throw new Error(oops);

  }

  }

  }

  sclSet = true;

  }

  }

  二、双亲委派模型

  ClassLoader的双亲委派模型中,各个ClassLoader之间的关系是通过组合关系来复用父加载器。当一个ClassLoader收到来类加载的请求,首先把该请求委派该父类ClassLoader处理,当父类ClassLoader无法处理时,才由当前类ClassLoader来处理。对于每个ClassLoader这个方式,也就是父类的优先于子类处理类加载的请求,那么也就是说任何一个请求第一次处理的便是最顶层的Bootstrap ClassLoader(启动类加载器)。

  类加载器的层级查找顺序依次为:启动类加载器,扩展类加载器,系统类加载器。系统类加载器是默认的应用程序类加载器。

  这样的好处是不同层次的类加载器具有不同优先级,比如所有Java对象的超级父类java.lang.Object,位于rt.jar,无论哪个类加载器加载该类,最终都是由启动类加载器进行加载,保证安全。即使用户自己编写一个java.lang.Object类并放入程序中,虽能正常编译,但不会被加载运行,保证不会出现混乱。那么有人会继续追问,如果自己再自定义一个类加载器来加载自己定义的java.lang.Object类呢? 这样做也是不会成功的,虚拟机将会抛出一异常。

  protected Class loadClass(String name, boolean resolve)

  throws ClassNotFoundException

  {

  synchronized (getClassLoadingLock(name)) {

  //检查该类是否已经加载过

  Class c = findLoadedClass(name);

  if (c == null) {

  //如果该类没有加载,则进入该分支

  long t0 = System.nanoTime();

  try {

  if (parent != null) {

  //当父类的加载器不为空,则通过父类的loadClass来加载该类

  c = parent.loadClass(name, false);

  } else {

  //当父类的加载器为空,则调用启动类加载器来加载该类

  c = findBootstrapClassOrNull(name);

  }

  } catch (ClassNotFoundException e) {

  //非空父类的类加载器无法找到相应的类,则抛出异常

  }

  if (c == null) {

  //当父类加载器无法加载时,则调用findClass方法来加载该类

  long t1 = System.nanoTime();

  c = findClass(name); //用户可通过覆写该方法,来自定义类加载器

  //用于统计类加载器相关的信息

  sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);

  sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);

  sun.misc.PerfCounter.getFindClasses().increment();

  }

  }

  if (resolve) {

  //对类进行link操作

  resolveClass(c);

  }

  return c;

  }

  }

  三、 经典应用场景

  Tomcat,类加载器架构,自己定义了多个类加载器,

  保证了同一个服务器的两个Web应用程序的Java类库隔离;

  保证了同一个服务器的两个Web应用程序的Java类库又可以相互共享;比如多个Spring组织的应用程序不能共享,会造成资源浪费;

  保证了服务器尽可能保证自身的安全不受不受部署Web应用程序影响;

  支持JSP应用的服务器,大多需要支持热替换(HotSwap)功能。

  OSGi(Open Service GateWay Initiative),是基于Java语言的动态模块化规范。已成为Java世界的“事实上”的模块化标准,最为熟悉的案例的Eclipse IDE。

​

java类加载器和双亲委派模型的更多相关文章

  1. @Java类加载器及双亲委派模型

    类与类加载器 虚拟机设计团队把类加载阶段的"通过一个类的全限定名来获取此类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个 ...

  2. Java自定义类加载器与双亲委派模型

    其实,双亲委派模型并不复杂.自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后copy一下就能用.但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制,这样显然不行.可是自定义类 ...

  3. 深入理解java虚拟机(九)类加载器以及双亲委派模型

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

  4. 【深入理解JVM】类加载器与双亲委派模型

    原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...

  5. 【深入理解JVM】:类加载器与双亲委派模型

    类加载器 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过一个类的全限定名来获取定义此类的二进制字 ...

  6. JVM类加载器以及双亲委派模型

    从java开发人员的角度来看,类加载器可以分为3种: 1.启动类加载器(Bootstrap ClassLoader),负责将存放在<JAVA_HOME>\lib目录中,或者被-Xbootc ...

  7. Java类加载机制以及双亲委派模型

    一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...

  8. 【深入理解JVM】类加载器与双亲委派模型 (转)

    出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...

  9. Tomcat 类加载器打破双亲委派模型

    我们分为4个部分来探讨: 1. 什么是类加载机制? 2. 什么是双亲委任模型? 3. 如何破坏双亲委任模型? 4. Tomcat 的类加载器是怎么设计的? 我想,在研究tomcat 类加载之前,我们复 ...

随机推荐

  1. 【gulp-sass】本地搭建sass开发环境

    首先去官网下载一下nodejs. 然后安装gulp: 选择一个目录执行命令行:npm init,一直回车生成package.json文件 再执行命令:npm install gulp --save-d ...

  2. Python之字符编码(一)

    一.了解字符编码的知识储备? 1.计算机基础知识? 计算机中所有的软件文件(包括:操作系统)都存储在硬盘,启动计算机,计算机需要把系统文件都去到内存中. 2.文本编辑器存取文件的原理(nodepad+ ...

  3. TCP 的那些事儿(下)(转)

    原文地址:http://kb.cnblogs.com/page/209101/ 作者: 陈皓  来源: 酷壳  发布时间: 2014-05-29 00:17  阅读: 18122 次  推荐: 19  ...

  4. 前端基础小标签3 H5新标签

    第二部分H5的新标签一.<!-- mark标签             1.用于显示页面中需要重点关注的内容,就像看书需要用荧光笔划重点一样             2.浏览器通常会用黄色显示m ...

  5. bzoj 2820 YY的GCD - 莫比乌斯反演 - 线性筛

    Description 神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种 傻×必 ...

  6. TCPCopy 使用方法

    TCPCopy 使用方法 TCPCopy是一种请求复制(所有基于tcp的packets)工具,可以把在线请求导入到测试系统中去.目前此工具已经广泛应用于国内各大互联网公司. TCPCopy七大功能 1 ...

  7. Flask学习【第9篇】:Flask-script组件

    Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任 ...

  8. Python logging 模块学习

    logging example Level When it's used Numeric value DEBUG Detailed information, typically of interest ...

  9. TI 多模雷达1843毫米波雷达做自动泊车(用了8个雷达)

    http://e2e.ti.com/blogs_/b/behind_the_wheel/archive/2019/01/09/how-mmwave-sensors-enable-autonomous- ...

  10. RHEL7防火墙策略设置

    注意查看firewall防火墙状态,并设置. 打开防火墙且没有放行端口的情况下rhel7这台机器是ping不通的. 放行端口需要永久放行,加--permernant,否则重启后失效,仍然无法访问该端口 ...