概述

ClassLoader的双亲托付模式:classloader 按级别分为三个级别:最上级 : bootstrap classLoader(根类载入器) ; 中间级:extension classLoader (扩展类载入器) 最低级 app classLoader(应用类载入器)。

根(Bootstrap)类载入器:该载入器没有父载入器。它负责载入虚拟机的核心类库,如java.lang.*等。比如java.lang.Object就是由根类载入器载入的。根类载入器从系统属性sun.boot.class.path所指定的文件夹中载入类库。

根类载入器的实现依赖于底层操作系统。属于虚拟机的实现的一部分,它并没有继承java.lang.ClassLoader类。

扩展(Extension)类载入器:它的父载入器为根类载入器。它从java.ext.dirs系统属性所指定的文件夹中载入类库,或者从JDK的安装文件夹的jre/lib/ext子文件夹(扩展文件夹)下载入类库,假设把用户创建的JAR文件放在这个文件夹下,也会自己主动由扩展类载入器载入。扩展类载入器是纯Java类,是java.lang.ClassLoader类的子类。

系统(System)类载入器:也称为应用类载入器。它的父载入器为扩展类载入器。

它从环境变量classpath或者系统属性java.class.path所指定的文件夹中载入类,它是用户自己定义的类载入器的默认父载入器。

系统类载入器是纯Java类。是java.lang.ClassLoader类的子类。

父子载入器并不是继承关系。也就是说子载入器不一定是继承了父载入器。

对于Java来说,java 虚拟机要将被用到的java类文件通过classLoader 载入到JVM内存中。而这个classloader就是bootstrap classloader。而对于APP而言,首先请求app 级来载入,继而请求extension classLoader,最后启动bootstrap classLoader 。

自己定义ClassLoader

public class MyClassLoader extends ClassLoader {//类载入器名称private String name;//载入类的路径private String path = "D:/";private final String fileType = ".class";public MyClassLoader(String name){//让系统类载入器成为该 类载入器的父载入器super();this.name = name;}public MyClassLoader(ClassLoader parent, String name){//显示指定该类载入器的父载入器super(parent);this.name = name;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}@Overridepublic String toString() {return this.name;}private byte[] loaderClassData(String name){InputStream is = null;byte[] data = null;ByteArrayOutputStream baos = new ByteArrayOutputStream();this.name = this.name.replace(".", "/");try {is = new FileInputStream(new File(path + name + fileType));int c = 0;while(-1 != (c = is.read())){baos.write(c);}data = baos.toByteArray();} catch (Exception e) {e.printStackTrace();} finally{try {is.close();baos.close();} catch (IOException e) {e.printStackTrace();}}return data;}@Overridepublic Class<?

> findClass(String name){ byte[] data = loaderClassData(name); return this.defineClass(name, data, 0, data.length); } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { //loader1的父载入器为系统类载入器 MyClassLoader loader1 = new MyClassLoader("loader1"); loader1.setPath("D:/lib1/"); //loader2的父载入器为loader1 MyClassLoader loader2 = new MyClassLoader(loader1, "loader2"); loader2.setPath("D:/lib2/"); //loader3的父载入器为根类载入器 MyClassLoader loader3 = new MyClassLoader(null, "loader3"); loader3.setPath("D:/lib3/"); Class clazz = loader2.loadClass("Sample"); Object object = clazz.newInstance(); } } public class Sample { public Sample(){ System.out.println("Sample is loaded by " + this.getClass().getClassLoader()); new A(); } } public class A { public A(){ System.out.println("A is loaded by " + this.getClass().getClassLoader()); } }

每个自己定义ClassLoader都必须继承ClassLoader这个抽象类,而每个ClassLoader都会有一个parent ClassLoader。我们能够看一下ClassLoader这个抽象类中有一个getParent()方法,这种方法用来返回当前 ClassLoader的parent,注意,这个parent不是指的被继承的类,而是在实例化该ClassLoader时指定的一个 ClassLoader,假设这个parent为null,那么就默认该ClassLoader的parent是bootstrap classloade。

上面解说了一下ClassLoader的作用以及一个最主要的载入流程,接下来我们说说ClassLoader使用了双亲托付模式进行类载入。

ClassLoader

双亲托付模式

通俗的讲,就是某个特定的类载入器在接到载入类的请求时,首先将载入任务托付给父类载入器。依次递归。假设父类载入器能够完毕类载入任务,就成功返回;仅仅有父类载入器无法完毕此载入任务时,才自己去载入。

为了更好的理解双亲托付模式,我们先自己定义一个ClassLoader,假设我们使用这个自己定义的ClassLoader载入 java.lang.String,那么这里String是否会被这个ClassLoader载入呢?

其实java.lang.String这个类并不会被我们自己定义的classloader载入。而是由bootstrap classloader进行载入,为什么会这样?实际上这就是双亲托付模式的原因,由于在不论什么一个自己定义ClassLoader载入一个类之前,它都会先 托付它的父亲ClassLoader进行载入,仅仅有当父亲ClassLoader无法载入成功后,才会由自己载入。

而在上面的样例中,由于 java.lang.String是属于java核心API的一个类,所以当使用自己定义的classloader载入它的时候。该 ClassLoader会先托付它的父亲ClassLoader进行载入(bootstrap classloader),所以并不会被我们自己定义的ClassLoader载入。

我们来看一下ClassLoader的一段源代码:

protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{  // 首先检查该name指定的class是否有被载入  Class c = findLoadedClass(name);  if (c == null) {  try {  if (parent != null) {  //假设parent不为null,则调用parent的loadClass进行载入  c = parent.loadClass(name, false);  }else{  //parent为null,则调用BootstrapClassLoader进行载入  c = findBootstrapClass0(name);  }  }catch(ClassNotFoundException e) {  //假设仍然无法载入成功,则调用自身的findClass进行载入              c = findClass(name);  }  }  if (resolve) {  resolveClass(c);  }  return c;  }

使用双亲托付模式长处

那么我们使用双亲托付模式有什么长处呢?

  1. 由于这样能够避免反复载入。当父亲已经载入了该类的时候,就没有必要子ClassLoader再载入一次。
  2. 考虑到安全因素,我们试想一下,假设不使用这样的托付模式,那我们就能够随时使用自己定义的String来动态替代java核心api中定义类型,这样会存在很大的安全隐患。而双亲托付的方式,就能够避免这样的情况,由于String已经在启动时被载入,所以用户自己定义类是无法载入一个自己定义的ClassLoader。

附:Android ClassLoader简单介绍

转载于:https://www.cnblogs.com/lxjshuju/p/7295018.html

android classloader双亲托付模式相关推荐

  1. 此计算机必须为委派而被信任_如何增强 ClassLoader 双亲委派模式 ?

    双亲委派模式 JVM加载类的实现方式,我们称为 双亲委托模型: 如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是把这个请求委托给自己的父加载器,每一层的类加载器都是如此,因此所 ...

  2. 类加载器以及双亲委派模式

    类加载器以及双亲委派模式 类加载器ClassLoader 类的加载流程的"加载"阶段是由类加载器完成的. JVM什么时候加载.class文件 当执行new操作时候 当执行Class ...

  3. Android中的代理模式

    Android中的代理模式 1. 什么是代理 比如我们生活中的找出租屋,需要去找中介进行寻找挑选.而这里的中介就是代理.列子中看出代理特点如下1. 租客跟中介要做成的最终目的是一致的就是租到房子(目标 ...

  4. 类加载器双亲委派模式

    双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只 ...

  5. Java 类加载体系之 ClassLoader 双亲委托机制

    Java 类加载体系之 ClassLoader 双亲委托机制 java 是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件 ...

  6. 范例解析:学习Android的IPC主板模式

    一.认识Android的IPC主板模式 系统架构设计最关键的任务就是组合(或称整合),而且最好是能与众不同.深具创新性组合.Android就擅用了主板模式,以通用性接口实践跨进程的IPC通信机制.由于 ...

  7. java安全沙箱(一)之ClassLoader双亲委派机制

    java是一种类型安全的语言,它有四类称为安全沙箱机制的安全机制来保证语言的安全性,这四类安全沙箱分别是: 类加载体系 .class文件检验器 内置于Java虚拟机(及语言)的安全特性 安全管理器及J ...

  8. android eng 模式,android 4.0 编译模式 eng - user 时遇到的有关问题

    android 4.0 编译模式 eng -- > user 时遇到的问题 关键词:android  4.0  user  eng  camera  nand  串口 平台信息: 内核:linu ...

  9. android主板接口定义,范例解析:学习Android的IPC主板模式

    一.认识Android的IPC主板模式 系统架构设计最关键的任务就是组合(或称整合),而且最好是能与众不同.深具创新性组合.Android就擅用了主板模式,以通用性接口实践跨进程的IPC通信机制.由于 ...

  10. android 勿扰模式代码,android Lollipop勿扰模式

    android的L新版本中增加了"打扰"的新功能,相信很多同学搞不明白.找了一篇介绍勿扰模式很好的文章,可惜是英文的,现翻译如下,相信读完此问,你会理解android对勿扰模式的设 ...

最新文章

  1. AI校招程序员最高薪酬曝光!腾讯80万年薪领跑,还送北京户口
  2. 世界杯规则终因IT而改变
  3. codeforces 465 C. No to Palindromes!(暴力+思维)
  4. 混合背包(信息学奥数一本通-T1270)
  5. C语言会生成字节码文件吗,什么是字节码文件?
  6. python pandas读取文件内容_python pandas读取大型文件
  7. 提高openfire最大连接数
  8. 低代码平台表单引擎技术方案选型
  9. 使用jwplayer插件播放视频
  10. 项目财务分析中的陷阱(3)(转)
  11. python 开发按键钢琴
  12. 实现文本框以及其背景(根据输入字数)动态拉伸
  13. 计算机如何默认一种打字法,如何设置输入法,教您如何设置电脑的默认输入法...
  14. 翻翻git之---不靠画全靠“演”,好看的自定义TextView translucent-android
  15. 高级移动位置(AML)与紧急位置服务(ELS)
  16. 【JS逆向系列】某乎x96参数与jsvmp初体验
  17. SqlServer各版本下载(2016-2019)
  18. 前端开发必备工具-网页调试工具
  19. ISO 8601 utc 时间
  20. 如何使用Zabbix官方模板轻松实现Docker容器监控?

热门文章

  1. 组队APP功能点定点NABCD分析
  2. C#结构体中的只写属性
  3. android启动之子系统切换
  4. 优秀的代码都是如何架构和分层的?
  5. 微服务架构下的数据一致性:概念及相关模式
  6. 你真的掌握 LVS、Nginx 及 HAProxy 的工作原理吗?
  7. 你们骂我骂的舒服么?
  8. Activity/Fragment最强生命周期总结
  9. micropython文件上传软件_4-3 为NodeMCU刷入MicroPython固件
  10. python基础之centos7源码安装python3