当我们在写完一个Java文件的时候,编译器会将.java文件编译成.class文件,然后当程序运行时,JVM首先会找到main方法所在类,并将main所在类的class文件字节码读到内存中,转换成JVM运行中运行时对应的Class对象,而执行这个加操作的就是类加载器(Classloader)。

类加载器的分类

Bootstrap ClassLoader:启动类加载器

负责将放在\lib目录中的,或被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。

我们在编写自定义加载器时,如果需要把加载器请求委派给启动类加载器,那么直接使用null代替即可。

Extension ClassLoader:拓展类加载器

负责加载在\lib\ext目录中的,或被java.ext.dirs系统变量所指定的路径中的所有类库。

Applicaiton ClassLoader:应用程序类加载器

用来加载ClassPath下的类,也就是我们自己写的类,如果程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器

双亲委派

如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是将请求委托给父加载器完成,依次向上,所有的类加载请求都会依次传到顶级的Bootstrap 类加载器中,只有当父加载器在可加载的范围内无法完成加载时才会将请求交给子类,子加载器才会尝试加载该类。

这种模型的好处就是保证了类不会重复加载,保证了程序的安全。

在ClassLoader中定义了双亲委派的loadClass方法

protected Class> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

synchronized (getClassLoadingLock(name)) {

// 1. 检查是否已经加载过。

Class c = findLoadedClass(name);

if (c == null) {

long t0 = System.nanoTime();

try {

if (parent != null) {

//2 .如果没有加载过,先调用父类加载器去加载

c = parent.loadClass(name, false);

} else {

// 3 如果没有加载过,且没有父类加载器,就用BootstrapClassLoader去加载

c = findBootstrapClassOrNull(name);

}

} catch (ClassNotFoundException e) {

// ClassNotFoundException thrown if class not found

// from the non-null parent class loader

}

if (c == null) {

//4. 如果父类加载器没有加载到,调用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) {

resolveClass(c);

}

return c;

}

}

复制代码

通过代码整理的双亲委派模型的大致流程:

首先检查指定名的里是否加载过,如果家在过了,就不用再重复加载,直接返回。如果没有加载过就判断是否还有父加载器,如果有,就交由父类加载器加载,或通过bootstrap类加载器加载。如果了父加载器和bootstrap类加载器都没有找到指定类,就调用当前类加载器的findClass来完成加载;

注意,默认的findClass方法中是直接抛出ClassNotFound异常的,所以我们需要自定义类加载器去重写这个方法。

protected Class> findClass(String name) throws ClassNotFoundException {

throw new ClassNotFoundException(name);

}

复制代码

继承ClassLoader对象,重写findClass方法,作用是找到指定的 class 文件,并转换成字节数组,然后转换成Class对象返回

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

//1. 覆盖findClass,来找到.class文件,并且返回Class对象

try {

String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";

InputStream is = getClass().getResourceAsStream(fileName);

if (is == null) {

//2. 如果没找到,return null

return null;

}

byte[] bytes = new byte[is.available()];

is.read(bytes);

//3. 将字节数组转换成了Class对象

return defineClass(name, bytes, 0, bytes.length);

} catch (Exception e) { e.printStackTrace(); }

return null;

}

复制代码

java的双亲委派_深入理解Java的类加载器及双亲委派机制相关推荐

  1. java逻辑第九章_深入理解jvm-(第九章)类加载及执行子系统的案例与实战

    转载自:http://blog.csdn.net/coslay/article/details/49564789 概述 在Class文件格式与执行引擎这部分中,用户的程序能直接影响的内容并不太多, C ...

  2. 深入理解Java虚拟机知乎_深入理解Java虚拟机(类文件结构)

    深入理解Java虚拟机(类文件结构) 欢迎关注微信公众号:BaronTalk,获取更多精彩好文! 之前在阅读 ASM 文档时,对于已编译类的结构.方法描述符.访问标志.ACC_PUBLIC.ACC_P ...

  3. java调用子系统代码_深入理解JAVA虚拟机-Idea远程执行本地Java代码 - Java 技术驿站-Java 技术驿站...

    今天在看深入理解JAVA虚拟机的9.3节,作者实现了一个远程执行功能.这个功能可以在远程服务器中临时执行一段程序代码,而去不依赖jdk版本,不改变原有服务端程序的部署,不依赖任何第三方库,不入侵原有的 ...

  4. java虚引用作用_深入理解Java中的引用(二)——强软弱虚引用

    深入理解Java中的引用(二)--强软弱虚引用 在上一篇文章中介绍了Java的Reference类,本篇文章介绍他的四个子类:强引用.软引用.弱引用.虚引用. 强引用(StrongReference) ...

  5. java 接口和虚构_深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  6. Java虚拟机不能满足_深入理解Java虚拟机--读书笔记1/3

    <深入理解Java虚拟机-JVM高级特性与最佳实践> Chap 2 Java内存区域与内存溢出异常 1.Java运行时数据区域 A.程序计数器:当前线程所执行字节码的行号指示器,线程私有( ...

  7. java虚拟机编译顺序_深入理解Java虚拟机(程序编译与代码优化)

    文章首发于微信公众号:BaronTalk,欢迎关注! 对于性能和效率的追求一直是程序开发中永恒不变的宗旨,除了我们自己在编码过程中要充分考虑代码的性能和效率,虚拟机在编译阶段也会对代码进行优化.本文就 ...

  8. java抽象类的属性_深入理解Java抽象类

    基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍,仍不理解的部分那一定是我讲的不够生动,记得留言提醒我. 好 ...

  9. java 执行字节码_深入理解java:1.2. 字节码执行引擎

    执行引擎是Java虚拟机的核心组成部分之一. 首先,想想C++和Java在编译和运行时到底有啥不一样? 下图左边,C++发布的就是机器指令, 而下图右边Java发布的是字节码,字节码在运行时通过JVM ...

最新文章

  1. 医药信息化:GMP/GSP之后
  2. [译]ASP.NET Core 2.0 部分视图
  3. Linux6.4通过PXE网络装机
  4. python限定方法参数类型、返回值类型、变量类型
  5. LUA __call
  6. shiro添加注解@RequiresPermissions无效
  7. SQL 每行随机产生数字
  8. 前端HTML以及HTML5(基本标签)
  9. 输入输出数组元素的函数重载_C ++函数重载| 查找输出程序| 套装3
  10. java输入做参数需要close吗_JAX-RS和java.time.LocalDate作为输入参数
  11. 还在用Random获取随机数?ThreadLocalRandom 性能更佳!
  12. python打电话播放语音_让电话录音也能看得见,录音一键转为文字
  13. python 决策树回归参数_python决策树之CART分类回归树详解
  14. Android 手机抓包工具 Packet Capture
  15. 计算机基础无纸化考试题库,计算机基础考试题库及答案
  16. python直方图规定化_OpenCV 直方图处理:直方图均衡和规定化(匹配)
  17. 2007中国优秀无线站点TOP50
  18. 快速排序C语言代码+辅助图+注释
  19. 【pytorch图像分类】AlexNet网络结构
  20. Unity DOTS1.0安装

热门文章

  1. POJ 1080 Human Gene Functions(DP:LCS)
  2. Thread中interrupt()interrupted()和isInterrupted()的区别
  3. #includeiostream与#includeiostream.h的区别
  4. ProcessOnLoading
  5. 26muduo_net库源码分析(二)
  6. mysql单机在线迁移_MySQL 不停服务 在线进行100亿数据迁移切换
  7. bvp解算器是什么_几种飞控的姿态解算算法
  8. 三维球体换算到二维_三维制图讲义04 - 基础几何体
  9. 目录代码php_php获取某个目录大小的代码
  10. 用c语言编电话薄系统,求助 哈稀表编电话薄程序(c语言) 算法