一、类加载器

1、在Java中,有两种类型的类加载器,分别是JVM自带的类加载器和用户自定义的类加载器。

2、JVM自带的类加载器有三种,如下:

根(Bootstrap)类加载器:该加载器没有父加载器,它负责加载虚拟机的核心类库,如java.lang.*等。它从系统属性sun.boot.class.path所指定的目录中加载类库,它的实现依赖于底层操作系统,属于虚拟机的实现的一部分,它并没有继承java.lang.ClassLoader类,因为它是用C++写的,无法在代码中访问该类。

扩展(Extension)类加载器:它的父加载器为根类加载器,它从java.ext.dirs系统属性所指定的目录中加载类库,或者从JDK的安装目录的jre\lib\ext子目录(扩展目录)下加载类库,如果把用户创建的jar文件放在该目录下,也会自动由扩展类加载器加载。它是纯Java类,是java.lang.ClassLoader类的子类。

系统(System)类加载器:也称为应用类加载器,它的父加载器为扩展类加载器。它从环境变量classpath或系统属性java.class.path所指定的目录中加载类,它是用户自定义的类加载器的默认父加载器。它是纯Java类,也是java.lang.ClassLoader类的子类。

如下代码所示,由于类的加载是将类的class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。而这个Class对象会包含一个负责加载该类的类加载器的引用,所以通过Class对象的getClassLoader方法就可以得到加载该类的类加载器。以下代码的运行结果是首先输出“null”,然后输出“sun.misc.Launcher$AppClassLoader@18fe7c3”,因为根类加载器它负责加载虚拟机的核心类库,所以代码“Class> clazz = Class.forName("java.lang.String")”会由根类加载器进行加载,而根类加载器是无法在代码中访问到的,所以“clazz.getClassLoader()”返回null代表根类加载器。

package com.jgao.classloader.test05;

class User {

}

public class Test {

public static void main(String[] args) throws ClassNotFoundException {

Class> clazz = Class.forName("java.lang.String");

System.out.println(clazz.getClassLoader());

clazz = Class.forName("com.jgao.classloader.test05.User");

System.out.println(clazz.getClassLoader());

}

}

3、用户自定义类加载器

除了以上JVM自带的加载器外,用户还可以定制自己的类加载器,所有用户自定义的类加载器需要继承java.lang.ClassLoader类。

二、父亲委托机制

1、父子加载器

类加载器用来把类加载到JVM中。从JDK 1.2开始,类的加载过程采用父亲委托机制,该机制能更好地保证Java平台的安全性。在委托机制中,各个加载器按照父子关系形成了树形结构,除了JVM自带的根类加载器以外,其余的类加载器都有且只有一个父类加载器,如下图:

需要注意的是加载器之间的父子关系实际上指的是加载器对象之间的包装关系,而不是类之间的继承关系,所以一对父子加载器可能是同一个加载器类的两个实例(在子加载器对象中包装了一个父加载器对象),也可能不是。如下图所示,这是java.lang.ClassLoader类的两个构造方法;当生成一个自定义的类加载器实例时,如果使用的是ClassLoader类的空参数的构造方法时(也就是没有指定它的父加载器),那么会使用 getSystemClassLoader() 方法返回的系统类加载器作为该类加载器的父加载器,所以在介绍系统类加载器时说它是用户自定义的类加载器的默认父加载器。而使用另外一个构造方法就可以指定父加载器。

2、父亲委托机制加载流程

如下图所示,当Java程序请求加载器loader2加载User类时,加载器load2首先从自己的命名空间中查找User类是否已经被加载了,如果已经加载,则直接返回代表User类的Class对象的引用。否则,loader2首先请求父加载器loader1代为加载,loader1再继续请求它的父加载器(系统类加载器)代为加载,系统类加载器再请求扩展类加载器代为加载,扩展类加载器再请求根类加载器代为加载。若根类加载器和扩展类加载器都不能加载,则系统类加载器尝试加载,若能加载成功,则将User所对应的Class对象的引用返回给loader1,loader1再将引用返回给loader2,从而成功将User类加载进虚拟机。若系统类加载器不能加载User类,则loader1尝试加载User类,若loader1也不能成功加载,则loader2尝试加载。若所有的父加载器及loader2本身都不能加载,则抛出ClassNotFoundException异常。

在这整个过程中,如果有一个类加载器能够成功加载User类,那么这个类加载器被称为定义类加载器,所有能成功返回Class对象的引用的类加载器(包括定义类加载器)都被称为初始类加载器。比如loader1实际加载了User类,则loader1为User类的定义类加载器,loader2和loader1为User类的初始类加载器。

3、父亲委托机制的优点

父亲委托机制的优点就是能够提高软件系统的安全性,因为在此机制下,用户自定义的类加载器不可能加载应该由父加载器加载的可靠类,从而防止不可靠甚至恶意的代码代替由父加载器加载的可靠代码。比如java.lang.Object类总是由根类加载器加载,其他任何用户自定义的类加载器都不可能加载含有恶意代码的java.lang.Object类。

三、其他

1、命名空间

每个类加载器都有自己的命名空间,命名空间由该类加载器及所有父加载器所加载的类组成。在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类;在不同的命名空间中,有可能会出现类的完整名字相同的两个类。比如有两个类加载器A和B,A类加载器已经加载了C这个类,那么B这个类加载器还能加载C这个类吗?这要分两种情况,如下:

A和B加载器不是父子关系:这时B这个类加载器还是可以加载C这个类

A和B加载器是父子关系:这时B这个类加载器就不可以加载C这个类,因为已经由A加载器加载过了,就不会再次进行加载

2、运行时包

由同一类加载器加载的属于相同包的类组成了运行时包。决定两个类是不是属于同一个运行时包,不仅要看它们的包名是否相同,还要看定义类加载器是否相同,只有属于同一运行时包的类才能互相访问包可见(即默认的访问级别)的类和类成员。这样的限制能避免用户自定义的类冒充核心类库的类,去访问核心类库的包可见成员。比如用户自定义了一个类java.lang.Spy,并由用户自定义的类加载器加载,由于java.lang.Spy和核心类库java.lang.*是由不同的类加载器加载,它们属于不同的运行时包,所以java.lang.Spy不能访问核心类库java.lang包中的包可见成员。

java 父委托机制优点_类加载器及父亲委托机制相关推荐

  1. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  2. java类加载器_类加载器

    回顾一下类加载过程 类加载过程:加载->连接->初始化.连接过程又可分为三步:验证->准备->解析. 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的 ...

  3. 【Java类加载机制】深入类加载器(二)自定义加密、解密类加载器

    类加载器原理 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口. 类加载 ...

  4. OSGi 规范和框架 OSGi框架类加载机制 Java默认类加载器机制和OSGI类加载器机制比较

    一.OSGi 规范 OSGi(Open Service Gateway Initiative) 技术是 Java 动态化模块化系统的一系列规范.OSGi 一方面指维护 OSGi 规范的 OSGi Al ...

  5. axure 富文本编辑器_Java的类加载器与双亲委托机制

    目录: 类加载器 java.lang.ClassLoader类 URLClassLoader与SecureClassLoader ClassLoader常见方法源码分析 双亲委托机制 图解 源码角度分 ...

  6. JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架...

    1.类加载器 ·简要介绍什么是类加载器,和类加载器的作用 ·Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader ...

  7. java 类加载 双亲委派_Java类加载器和双亲委派机制

    前言 之前详细介绍了Java类的整个加载过程(类加载机制详解).虽然,篇幅较长,但是也不要被内容吓到了,其实每个阶段都可以用一句话来概括. 1)加载:查找并加载类的二进制字节流数据. 2)验证:保证被 ...

  8. 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

    转载自 深入JVM系列(三)之类加载.类加载器.双亲委派机制与常见问题 一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用 ...

  9. JVM入门(位置、体系结构、类加载器、双亲委派机制、沙箱安全机制、Native、PC寄存器、方法区、堆(新生区{伊甸园区、幸存区}、养老区、永久区)、OOM、GC算法、JMM)

    目录 一.JVM的位置 二.JVM的体系结构 三.类加载器 1.类加载器举例 2. JVM中提供了三层的ClassLoader 3. 双亲委派机制(重要) 3.1 工作原理 3.2.优点 四.沙箱安全 ...

最新文章

  1. ping 丢包 网络摄像头_视频监控系统的摄像头掉线看交换机连接注意事项
  2. [云炬创业基础笔记]第六章商业模式测试6
  3. OpenGL Multiple Scissors多个剪刀的实例
  4. UDP穿透NAT原理解析
  5. 浅谈微信smali注入
  6. 办公自动化-world转pdf-0223
  7. linux修改py内容,python中修改文件行内容
  8. [Python] L1-001. Hello World-PAT团体程序设计天梯赛GPLT
  9. mysql id div 1000000,mysql – 如何使用随机数据生成1000000行?
  10. 一个基于DataTable的后台框架的实现
  11. python 串口write 返回值_MicroPython 玩转硬件系列4:串口小实验
  12. 内存映射函数remap_pfn_range学习——示例分析(1)
  13. unity之小地图和聊天室
  14. 在Ubuntu Kylin 优麒麟系统中安装 Etcher镜像烧录软件
  15. ftp linux登录的命令行,linux登录ftp:lftp命令
  16. 获取浏览器唯一标识_探讨浏览器指纹 fingerprint
  17. QNET:APP弱网络测试专家
  18. 用Date计算日期相差多少天
  19. 未封装的扩展程序是什么意思_晶圆级封装是什么意思?
  20. 011 数据恢复(原理)

热门文章

  1. 服务器creo怎么添加配置文件,Creo 2.0 配置文件选项以及实例
  2. 苹果手机充电口接触不良怎么办_充电器接触不良怎么办 高手来教你几招-装修攻略...
  3. mysql+excel:数据分析----餐饮业日销售情况分析仪
  4. 苹果自动驾驶项目,黄了吗
  5. [linux]循序渐进学运维-基础命令篇-文件的归档和压缩
  6. Matlab实现有向图的关联矩阵和邻接矩阵的转换
  7. NO2!阿里研究院入选中国企业智库系统影响力榜...
  8. 对​ e 妹儿公司的字符串处理
  9. 使用Python+PyTorch预测野外火灾!
  10. 2006中国富豪排行榜