31、JVM类加载机制

  虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型, 这就是虚拟机的类加载机制。
  类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading) 7个阶段。其中验证、准备、解析3个部分统称为连接(Linking)。

  加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。注意,这里笔者写的是按部就班地“开始”,而不是按部就班地“进行”或“完成”,强调这点是因为这些阶段通常都是互相交叉地混合式进行的,通常会在一个阶段执行的过程中调用、激活另外一个阶段。
  类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。 这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。

31.1、双亲委派模型

  从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现(只限于HotSpot),是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全都继承自抽象类java.lang.ClassLoader。
  从Java开发人员的角度来看,类加载器还可以划分得更细致一些,绝大部分Java程序都会使用到以下3种系统提供的类加载器。
  启动类加载器(Bootstrap ClassLoader): 这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。
  扩展类加载器(Extension ClassLoader): 这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
  应用程序类加载器(Application ClassLoader): 这个类加载器由sun.misc.Launcher$App-ClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
  我们的应用程序都是由这3种类加载器互相配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如图所示。

  图中展示的类加载器之间的这种层次关系,称为类加载器的双亲委派模型(Parents Delegation Model)。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码。
  双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
  使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。
  双亲委派模型对于保证Java程序的稳定运作很重要,但它的实现却非常简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法之中,代码清单,逻辑清晰易懂:先检查类是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。

31.2、描述 Java类加载器的工作原理及其组织结构。

  Java 类加载器的作用就是在运行时加载类。
  Java 类加载器基于三个机制:委托性、可见性和单一性。
  1、委托机制是指双亲委派模型。 当一个类加载和初始化的时候,类仅在有需要加载的时候被加载。假设你有一个应用需要的类叫作Abc.class,首先加载这个类的请求由Application 类加载器委托给它的父类加载器 Extension 类加载器,然后再委托给Bootstrap 类加载器。Bootstrap类加载器会先看看rt.jar 中有没有这个类,因为并没有这个类,所以这个请求又回到 Extension 类加载器,它会查看 jre/lib/ext 目录下有没有这个类,如果这个类被 Extension 类加载器找到了,那么它将被加载,而Application 类加载器不会加载这个类;而如果这个类没有被 Extension 类加载器找到,那么再由 Application 类加载器从 classpath中寻找,如果没找到,就会抛出异常。
双亲委托机制的优点就是能够提高软件系统的安全性。因为在此机制下,用户自定义的类加载器不可能加载本应该由父加载器加载的可靠类,从而防止不可靠的恶意代码代替由父类加载器加载的可靠代码。如java.lang.Object类总是由根类加载器加载的,其他任何用户自定义的类加载器都不可能加载含有恶意代码的 java.lang.Object 类。
  2、可见性原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。
  3、单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。

  Java 的类加载器有三个,对应 Java 的三种类:
  BootstrapLoader // 负责加载系统类 (指的是内置类,像String)
  ExtClassLoader // 负责加载扩展类(就是继承类和实现类)
  AppClassLoader // 负责加载应用类(程序员自定义的类)
  Java 提供了显式加载类的API:Class.forName(classname)。

Java常见面试题汇总-----------JVM专题(Java类加载机制)相关推荐

  1. 【Java常见面试题】JVM篇

    导航: [黑马Java笔记+踩坑汇总]JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud+黑马旅游+谷粒商城+学成在线+牛客面试题 目录 1.说说你了解的JV ...

  2. 2020 Java常见面试题汇总

    1-10期 [10期]Redis 面试常见问答 [09期]说说hashCode() 和 equals() 之间的关系? [08期]说说Object类下面有几种方法呢? [07期]Redis中是如何实现 ...

  3. Java常见面试题(JVM)

    JVM内存分哪几个区,每个区的作用是什么? java虚拟机主要分为以下一个区: 方法区: 1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的 ...

  4. Java常见面试题汇总(一)

    1)什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节 ...

  5. Java常见面试题汇总

    动力节点Java培训最新上线Java实验班,等你来测试自己适不适合学习Java编程哦! 今天的主题我们来谈谈求职,每个程序员的生涯总有几次求职经历,对于求职者而言,在面对自己心仪的公司之前总要做足成分 ...

  6. Java常见面试题 + 答案

    Java常见面试题 + 答案 一.Java 基础 二.容器 三.多线程 四.反射 五.对象拷贝 六.Java Web 七.异常 八.网络 九.设计模式 十.Spring / Spring MVC 十一 ...

  7. Java常见面试题,2021年及答案汇总

    Java常见面试题,2021年及答案汇总 其实,博主还整理了,更多大厂面试题,直接下载吧 下载链接:高清172份,累计 7701 页大厂面试题 PDF 1.什么是ThreadPoolExecutor? ...

  8. java中级程序员面试题_中级Java程序员常见面试题汇总

    下面是一些中级Java程序员常见面试题汇总,你可以用它来好好准备面试. 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器 ...

  9. java常见面试题及答案 11-20(JVM)

    11.JVM内存分哪几个区,每个区的作用是什么? java虚拟机主要分为以下一个区: 方法区: 1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法 ...

  10. Java常见面试题及答案汇总

    面临金三银四黄金跳槽季,不光是很多在职人员跃跃欲试,也有很多大学生积极地加入到应聘行列.作为技术出身的我们,找工作的一大前提就是技术是否能过关.而对于Java程序员来说,至少是两关的面试,这首个关卡就 ...

最新文章

  1. SQL Server中DateTime格式转换
  2. java通过代码显示特定窗体,如何把这两段代码在一个窗体显示,类似于windows自带的扫雷一样...
  3. jTable保存到mysql_怎么把从数据库里的数据输到JTABLE里面
  4. 必看:Kubernetes 开发环境对比
  5. wxWidgets:wxResourceTranslationsLoader类用法
  6. sort()函数、C++
  7. 石油与天然气行业中数据报表分析
  8. VS2012打开项目 提示Asp.net4.0未在web服务器上注册的解决方案
  9. 为什么要使用向量化?
  10. Html元素~~标签学习
  11. 蓝桥杯 BASIC-9 特殊回文数
  12. 阿里云云计算 50 云监控的使用
  13. 比Everything、listary、DocFetcher还好用的桌面文档搜索软件 - bbdoc
  14. 服务器系统用哪个版本好,windows服务器系统哪个版本好用
  15. vs2003远程调试总结
  16. Python 3.9 新特性速览 - Ricequant米筐量化
  17. ESP8266获取B站粉丝数
  18. 一台液晶显示器台式计算机总耗电量,一天一台电脑用多少电
  19. 【GNN】时空图网络 tensorflow 实现
  20. BC30 KiKi和酸奶

热门文章

  1. 【STM32F429】第5章 RTX5操作系统移植(MDK AC6)
  2. 变色龙引导安装黑苹果 遇到的问题的解决办法
  3. Huffman-哈夫曼编码算法详解
  4. dos命令大全 基础命令+网络的常用命令
  5. android开发学习-日常用到的好东西-常用技巧分享
  6. 深入游戏变速底层原理以及内核变速的实现
  7. 三星显示屏测试软件,MagicTune(三星显示器调节工具)
  8. html自动写对联,html+css纯代码给自己的网站添加对联广告位
  9. 互联网科普-什么是淘宝
  10. 怎样添加图片到黑莓7290手机里?