1. ##默认的三个类加载器
  2. Java默认是有三个ClassLoader,按层次关系从上到下依次是:
  3.  
  4. - Bootstrap ClassLoader
  5. - Ext ClassLoader
  6. - System ClassLoader
  7.  
  8. Bootstrap ClassLoader是最顶层的ClassLoader,它比较特殊,是用C++编写集成在JVM中的,是JVM启动的时候用来加载一些核心类的,比如:`rt.jar`,`resources.jar`,`charsets.jar`,`jce.jar`等,可以运行下面代码看都有哪些:
  9. ```
  10. URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
  11. for (int i = 0; i < urls.length; i++) {
  12. System.out.println(urls[i].toExternalForm());
  13. }
  14. ```
  15. 其余两个ClassLoader都是继承自`ClassLoader`这个类。Java的类加载采用了一种叫做“双亲委托”的方式(稍后解释),所以除了`Bootstrap ClassLoader`其余的ClassLoader都有一个“父”类加载器, 不是通过继承,而是一种包含的关系。
  16. ```
  17. //ClassLoader.java
  18. public abstract class ClassLoader {
  19. ...
  20. // The parent class loader for delegation
  21. private ClassLoader parent;
  22. ...
  23. ```
  24. ##“双亲委托”
  25. 所谓“双亲委托”就是当加载一个类的时候会先委托给父类加载器去加载,当父类加载器无法加载的时候再尝试自己去加载,所以整个类的加载是“自上而下”的,如果都没有加载到则抛出`ClassNotFoundException`异常。
  26.  
  27. 上面提到Bootstrap ClassLoader是最顶层的类加载器,实际上Ext ClassLoaderSystem ClassLoader就是一开始被它加载的。
  28.  
  29. Ext ClassLoader称为扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有的jar(包括自己手动放进去的jar包)。
  30.  
  31. System ClassLoader叫做系统类加载器,负责加载应用程序classpath目录下的所有jarclass文件,包括我们平时运行jar包指定cp参数下的jar包。
  32.  
  33. 运行下面的代码可以验证上面内容:
  34. ```
  35. ClassLoader loader = Debug.class.getClassLoader();
  36. while(loader != null) {
  37. System.out.println(loader);
  38. loader = loader.getParent();
  39. }
  40. System.out.println(loader);
  41. ```
  42.  
  43. ##“双亲委托”的作用
  44. 之所以采用“双亲委托”这种方式主要是为了安全性,避免用户自己编写的类动态替换Java的一些核心类,比如String,同时也避免了重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类,如果相互转型的话会抛`java.lang.ClassCaseException`.
  45.  
  46. ##自定义类加载器
  47. 除了上面说的三种默认的类加载器,用户可以通过继承`ClassLoader`类来创建自定义的类加载器,之所以需要自定义类加载器是因为有时候我们需要通过一些特殊的途径创建类,比如网络。
  48.  
  49. 至于自定义类加载器是如何发挥作用的,`ClassLoader`类的loadClass方法已经把算法定义了:
  50. ```
  51. protected synchronized Class<?> loadClass(String name, boolean resolve)
  52. throws ClassNotFoundException
  53. {
  54. // First, check if the class has already been loaded
  55. Class c = findLoadedClass(name);
  56. if (c == null) {
  57. try {
  58. if (parent != null) {
  59. c = parent.loadClass(name, false);
  60. } else {
  61. c = findBootstrapClassOrNull(name);
  62. }
  63. } catch (ClassNotFoundException e) {
  64. // ClassNotFoundException thrown if class not found
  65. // from the non-null parent class loader
  66. }
  67. if (c == null) {
  68. // If still not found, then invoke findClass in order
  69. // to find the class.
  70. c = findClass(name);
  71. }
  72. }
  73. if (resolve) {
  74. resolveClass(c);
  75. }
  76. return c;
  77. }
  78. ```
  79.  
  80. >1. Invoke `findLoadedClass(String)` to check if the class has already been loaded.
  81.  
  82. >2. Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
  83.  
  84. >3. Invoke the `findClass(String)` method to find the class.
  85.  
  86. 看上面的Javadoc可以知道,自定义的类加载器只要重载`findClass`就好了。
  87. ##Context ClassLoader
  88. 首先JavaClassLoader就上面提到的四种,`Bootstrap ClassLoader``Ext ClassLoader``System ClassLoader`以及用户自定义的,所以`Context ClassLoader`并不是一种新的类加载器,肯定是这四种的一种。
  89.  
  90. 首先关于类的加载补充一点就是如果类A是被一个加载器加载的,那么类A中引用的B也是由这个加载器加载的(如果B还没有被加载的话),通常情况下就是类B必须在类Aclasspath下。
  91.  
  92. 但是考虑多线程环境下不同的对象可能是由不同的ClassLoader加载的,那么当一个由ClassLoaderC加载的对象A从一个线程被传到另一个线程ThreadB中,而ThreadB是由ClassLoaderD加载的,这时候如果A想获取除了自己的classpath以外的资源的话,它就可以通过`Thread.currentThread().getContextClassLoader()`来获取线程上下文的ClassLoader了,一般就是ClassLoaderD了,可以通过`Thread.currentThread().setContextClassLoader(ClassLoader)`来显示的设置。
  93.  
  94. ##为什么要有Context ClassLoader
  95. 之所以有Context ClassLoader是因为Java的这种“双亲委托”机制是有局限性的:
  96.  
  97. - 举网上的一个例子:
  98.  
  99. > JNDI为例,JNDI的类是由bootstrap ClassLoaderrt.jar中间载入的,但是JNDI具体的核心驱动是由正式的实现提供的,并且通常会处于-cp参数之下(注:也就是默认的System ClassLoader管理),这就要求bootstartp ClassLoader去载入只有SystemClassLoader可见的类,正常的逻辑就没办法处理。怎么办呢?parent可以通过获得当前调用Thread的方法获得调用线程的>Context ClassLoder 来载入类。
  100.  
  101. - 我上面提到的加载资源的例子。
  102.  
  103. `Contex ClassLoader`提供了一个突破这种机制的后门。
  104.  
  105. Context ClassLoader一般在一些框架代码中用的比较多,平时写代码的时候用类的ClassLoader就可以了。
  106.  
  107. ##参考链接
  108. [http://stackoverflow.com/questions/1771679/difference-between-threads-context-class-loader-and-normal-classloader][1]
  109.  
  110. [1]: http://stackoverflow.com/questions/1771679/difference-between-threads-context-class-loader-and-normal-classloader

Java基础—ClassLoader的理解的更多相关文章

  1. Java基础—ClassLoader的理解(转)

    默认的三个类加载器 Java默认是有三个ClassLoader,按层次关系从上到下依次是: Bootstrap ClassLoader Ext ClassLoader System ClassLoad ...

  2. java的classLoader原理理解和分析

    java的classLoader原理理解和分析 学习了:http://blog.csdn.net/tangkund3218/article/details/50088249 ClassNotFound ...

  3. Java 基础:认识&理解关键字 native 实战篇

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 泥瓦匠初次遇见 navicat 是在 java.lang.Object 源码中的一个hashCode方 ...

  4. Java基础之深入理解Class对象与反射机制

    深入理解Class对象 RRIT及Class对象的概念 RRIT(Run-Time Type Identification)运行时类型识别.在<Thinking in Java>一书第十四 ...

  5. Java基础系列-深入理解==和equals的区别(一)

    一.前言 说到==和equals的问题,面试的时候可能经常被问题到,有时候如果你真的没有搞清楚里边的原因,被面试官一顿绕就懵了,所以今天我们也来彻底了解一下这个知识点. 二.==和equals的作用 ...

  6. java基础强化——深入理解反射

    目录 1.从Spring容器的核心谈起 2. 反射技术初探 2.1 什么是反射技术 2.2 类结构信息和java对象的映射 3 Class对象的获取及需要注意的地方 4. 运行时反射获取类的结构信息 ...

  7. java基础强化——深入理解java注解(附简单ORM功能实现)

    目录 1.什么是注解 2. 注解的结构以及如何在运行时读取注解 2.1 注解的组成 2.2 注解的类层级结构 2.3 如何在运行时获得注解信息 3.几种元注解介绍 3.1 @Retention 3.2 ...

  8. Java基础-四大特性理解(抽象、封装、继承、多态)

    抽象: 象就是有点模糊的意思,还没确定好的意思. 就比方要定义一个方法和类.但还没确定怎么去实现它的具体一点的子方法,那我就可以用抽象类或接口.具体怎么用,要做什么,我不用关心,由使用的人自己去定义去 ...

  9. [java基础]一文理解java多线程必备的sychronized关键字,从此不再混淆!

    java并发编程中最长用到的关键字就是synchronized了,这里讲解一下这个关键字的用法和容易混淆的地方. synchronized关键字涉及到锁的概念, 在java中,synchronized ...

随机推荐

  1. Jenkins进阶系列之——07更改Jenkins的主目录

    Jenkins默认会存放在用户主目录下的.jenkins文件夹中 如:Linux root用户:/root/.jenkins 注意:这是linux版本的.windows系统请自行更改.这个值在Jenk ...

  2. 通过爬虫代理IP快速增加博客阅读量——亲测CSDN有效!

    写在前面 题目所说的并不是目的,主要是为了更详细的了解网站的反爬机制,如果真的想要提高博客的阅读量,优质的内容必不可少. 了解网站的反爬机制 一般网站从以下几个方面反爬虫: 1. 通过Headers反 ...

  3. java中String类型变量的赋值问题

    第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...

  4. web安全——简介

    简介 不对外提供服务是最安全的. 安全是基于信任.如果信任失败了,则没有安全.比如你给一个ip加白名单,结果这个ip对你发动了安全攻击. 在非常明确需要提供服务的时候才对外提供服务,即白名单.其他的全 ...

  5. Orchard用LiveWriter写博客

    本文链接:http://www.cnblogs.com/souther/p/4544241.html Orchard本身提供一个内建的管理面板来写博客,许多人更喜欢采用客户端提交的方式,例如Windo ...

  6. $().each() 与 $.each()解析

    在jquery 中我们可以选择$().each() 与 $.each() 进行迭代对象和数组 $(items).each(function(){ //item }) , 而后者则 $.each(ite ...

  7. 编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]

    前言 自从.NET出现后,关于CLR异常机制的讨论就几乎从未停止过.迄今为止,CLR异常机制让人关注最多的一点就是“效率”问题.其实,这里存在认识上的误区,因为正常控制流程下的代码运行并不会出现问题, ...

  8. [C#]二维码(QR Code)生成与解析

    写在前面 经常在大街上听到扫码送什么什么,如果真闲着没事,从头扫到位,估计书包都装满了各种东西.各种扫各种送,太泛滥了.项目中从没接触过二维码的东东,最近要使用,就扒了扒网络,发现关于解析二维码的类库 ...

  9. linux 安装webbench

    webbench :1.5  http://soft.vpser.net/test/webbench/webbench-1.5.tar.gz从官网下载webbench-1.5.tar.gz1.解压 t ...

  10. mysql-5.7.9-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法

    问题背景 最新解压版本的mysql 解压安装的时候报错 D:\mysql-5.7.9-winx64\bin>net start mysql MySQL 服务正在启动 . MySQL 服务无法启动 ...