第六章 深入分析ClassLoader工作机制
补充(非书中):
Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取Java字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。
Java 中的类加载器大致可以分成两类:
一类是系统提供的:
- 引导类加载器(bootstrapclass loader):它用来加载 Java 的核心库,是用原生代码而不是java来实现的,并不继承自java.lang.ClassLoader,除此之外基本上所有的类加载器都是java.lang.ClassLoader类的一个实例。
- 扩展类加载器(extensionsclass loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录(一般为%JRE_HOME%/lib/ext)。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(systemclass loader或 App class loader):它根据当前Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader() 来获取它。
另外一类则是由 Java 应用开发人员编写的:
- 开发人员可以通过继承java.lang.ClassLoader 类的方式实现自己的类加载器,以满足一些特殊的需求
classLoader是类加载器,负责将Class加载到JVM中,还有一个作用是审查每个类由谁加载,它是一种父优先的等级加载机制。
还有一个任务是,将class字节码重新解析成JVM统一要求的对象格式。
加载类过程:
假如loader2的parent为loader1,loader1的parent为system class loader。假设loader2被要求装载类MyClass,在parent delegation模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载MyClass。若系统装载器能成功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再将reference返回给loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1会尝试装载MyClass,若loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能装载,则装载失败。
6.1 ClassLoader类结构分析
defineClass(byte[], int, int): 将byte字节流解析成JVM能识别的class对象。
findClass(String):
loadClass(String): 获取class对象。
resolveClass(Class<?>):
ClassLoader是抽象类,有很多子类,如果我们要实现自己的ClassLoader,一般会继承URLClassLoader, 做修改就好了。
6.2 ClassLoader的等级加载机制
JVM提供三层ClassLoader,这三层ClassLoader可以分为两种类型
(1)Bootstrap ClassLoader: 加载JVM自身工作需要的类,完全由JVM自己控制,别人访问不到这个类,没有高一级的加载器,也没有子加载器。
(2)ExtClassLoader:
(3)AppClassLoader:
如果我们要实现自己的类加载器,不管是直接实现抽象类ClassLoader,还是继承URLClassLoader,或其他子类,它的父加载器都是AppClassLoader。
ExtClassLoader和AppClassLoader都继承了URLClassLoader类。
JVM加载class文件到内存有两种方式:
隐式加载:不在代码中调用ClassLoader来加载需要的类,而是通过JVM来自动加载需要的类到内存的方式。比如当在类中继承或引用某个类时,JVM发现其不在内存中,就会自动加载到内存。
显示加载:通过ClassLoader类来加载一个类的方式,this.getClass.getClassLoader().loadClass()或者Class.forName(). 或者我们自己实现的ClassLoader的findClass()方法。
6.3 如何加载class文件
三个步骤:
1 找到.class文件并把这个文件包含的字节码加载到内存。
2 字节码校验,Class类数据结构分析以及相应的内存分配和最后的符号表链接
3 类中静态属性和初始化赋值,已经静态块的执行等。
6.3.1 加载字节码到内存
URLClassLoader如何实现findclass()的,URLCclassLoader中通过一个URLClassPath类帮助取得要加载的class文件字节流,而这个URLClasspath定义了到哪里去找这个
class文件,如果找到,再读它的byte字节流,通过definClass()来创建类对象。根据路径的不同(是文件还是jar包)来创建FIleLoader或JarLoader.
6.3.2 验证与解析
字节码验证,验证格式正确,行为正确。
类准备,这个阶段准备代表每个类中定义的字段,方法和实现接口所必须的数据结构。
解析,装入类所引用的其他所有类。
6.3.3 初始化class对象
执行静态初始化器,静态字段会为初始化为默认值。
6.4 常见加载类错误分析
6.4.1 ClassNotFoundException
显示加载类三种方法:
Class.forName();
ClassLoader.loadClass()
ClassLoader.findSystemClass()
6.4.2 NoClassDefFoundError
类可能没加包名。
6.4.3 UnsatisfiedLinkError
可能是误删了lib文件
6.4.4 ClassCastExcetption
JVM做类型转换的检查规则:
- 普通对象,对象必须是目标类的实例或是目标类子类的实例。如果目标类是接口,那么可以把它当做实现了该接口的一个子类。
- 对于数组类型,目标类型必须是数组类型或java.lang,Object, java.lang,Clonble, java.io.serializable
如果不满足上面的规则,JVM就会报错:
要想避免这个错误 有两种方式:
容器类型中显示地指明容器对象类型,
通过instanceof检查是不是目标类型,然后在强转。
6.4.5 ExceptinInInitializerError
6.5 常用的ClassLoader分析
这里分析了servlet的ClassLoader
6.6 如何实现自己的ClassLoader
为什么要实现自己的classLoader
在自己的路径下查找自定义的class文件,不一定在classPath下面。
对我们的类做特殊处理,比如加密传输类在网络之间。这就需要在加载到JVM之前先解密。
可以定义类的实现机制,实现热部署。
6.6.1 加载自定义路径下的class文件
6.6.2 加载自定义格式的class文件
6.7 实现类的热部署
JVM在加载类之前会检查类是否已经被加载过,也就是要调用findLoadedClass()方法查看是否能返回类实例
JVM表示两个类是否是同一个类有两个条件:
一是看类的完整类名是否一样。
二是看加载这个类的ClassLoader是否是同一个(是指ClassLoader实例是否是同一个)。
实现热部署:可以用ClassLoader的两个实例加载同名的类。
6.8 java应不应该动态加载类
JAVA修改一个类,必须重启JVM。
第六章 深入分析ClassLoader工作机制的更多相关文章
- 《精通Spring4.X企业应用开发实战》读后感第六章(内部工作机制、BeanDefinition、InstantiationStrategy、BeanWrapper)
- 深入理解ClassLoader工作机制(jdk1.8)
ClassLoader 顾名思义就是类加载器,ClassLoader 作用: 负责将 Class 加载到 JVM 中 审查每个类由谁加载(父优先的等级加载机制) 将 Class 字节码重新 ...
- Android群英传笔记——第六章:Android绘图机制与处理技巧
Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...
- 理解ClassLoader工作机制
package com.ioc; public class Test { public static void main(String[] args) throws ClassNotFoundExce ...
- Java Web 深入分析(5) Java ClassLoader 工作机制
Classloader 有3个作用 将class加载到JVM中去 审查每个类由谁去加载,是一种父优先的等级加载 把Class字节码统一编译成JVM统一要求的对象格式 ClassLoader的等级加载机 ...
- ClassLoader工作机制
阅读目录 一.ClassLoader概念 二.JVM平台提供三层classLoader 三.JVM加载class文件到内存有两种方式 四.ClassLoader加载类的过程 五.自定义类加载器 六.实 ...
- Java Web ClassLoader工作机制
一.ClassLoader的作用: 1.类加载机制:父优先的等级加载机制 2.类加载过程 3.将Class字节码重新解析成JVM统一要求的对象格式 二.ClassLoader常用方法 1.define ...
- ClassLoader 工作机制
ClassLoader 采用上级委托接待机制加载 class JVM 平台提供三层 ClassLoader 1.Bootstrap ClassLoader:主要加载 JVM 自身工作需要的类 2.Ex ...
- 第2章 深入分析java I/O的工作机制(上)
java的I/O操作类在包java.io下,大致分成4组: 所有文件的存储都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再存储这些字节到磁盘.在读取文件时,也是一个 ...
随机推荐
- 报错HTTP Status 500 - The given object has a null identifier: cn.itcast.entity.Customer; nested exception is org.hibernate.TransientObjectException: The given object has a null identifier:
在使用模型驱动封装的时候,要保证表单中name属性名和类中属性名一致,否则将会报错如下: HTTP Status 500 - The given object has a null identifie ...
- 通过实例深入理解HTML5/CSS3/SVG/WebGL的技术本质
常常听到人们对于HTML5的讨论,看了页面头部这个那个就是Html5,误认为HTML5只是新增些标签“而已”,学完了W3School似乎就理解了.实际上很多从业人员并没有深入理解业界为什么要推出HTM ...
- JavaEE 技术体系
JavaEE 技术体系总结: 一:常见模式与工具 设计模式,流行的框架与组件 常见的设计模式,编码必备 Spring5,做应用必不可少的最新框架 MyBatis,玩数据库必不可少的组件 二:工程化与工 ...
- laravel利用composer安装
composer create-project laravel/laravel --prefer-dist blog prefer:提升,提拔 dist:距离 blog 创建的项目文件夹名称 lara ...
- 下载并安装Prism5.0库(纯汉语版)
Prism5.0中包含了文档,WPF代码示例,程序集.本篇告诉你从哪里获取程序集和代码示例,还有NuGet包的内容. 对于新功能,资产,和API的更改信息,请看Prism5.0新内容. 文档 Pris ...
- docker 部署一个 aspnetmvc 程序
准备mvc的程序[asp.net mvc5 网站] 使用刚才创建的镜像,并把上诉文件目录挂载到iis指定磁盘docker run -d -p 83:80 --name docker-drgs -v ...
- MSSQL数据库分区表
http://blog.csdn.net/lgb934/article/details/8662956 http://database.9sssd.com/mssql/art/951
- ASP调用存储过程访问SQL Server
ASP调用存储过程访问SQL Server 2011-02-15 10:22:57 标签:asp 数据库 sQL 存储过程 Server ASP和存储过程(Stored Procedures)的文章 ...
- kali视频学习(6-10)
第三周 kali视频(6-10)学习 6.信息搜集之主机探测 7.信息搜集之主机扫描(nmap使用) 8.信息搜集之指纹识别 9.信息搜集之协议分析 10.漏洞分析之OpenVAS安装 6.信息搜集之 ...
- 通信对象System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于“出错”状态。
问题描述:在客户端站点访问WCF服务后,在页面停留时间过长,客户端站点将会报错.报错内容如下: 通信对象System.ServiceModel.Channels.ServiceChannel 无法用于 ...