深入了解java虚拟机(JVM) 第十二章 类加载器
一、什么是类加载器
类加载器是一个用来加载类文件的类,Java源代码通过javac编译器编译成类文件,然后JVM来执行类文件中的字节码来执行程序。需要注意的是,只有被同一个类加载器加载的类才可能会相等。相同字节码被不同的类加载器加载的类不相等。
二、类加载器分类
1.启动类加载器
由C++实现,是虚拟机的一部分,用于加载javahome下的lib目录下的类;
2.扩展类加载器
加载javahome下/lib/ext目录中的类;
3.应用程序类加载器
加载用户类路径上的所指定的类库,也就是我们所用的类加载器;
三、自定义加载器
在jvm中,除了以上三种类加载器外,我们还可以自定义加载器,自定义加载器的方法有三步
1.定义一个类继承classloader
2.重写loadClass方法
3.实例化class对象
我们看下面的例子:
package com.example.demo;
import java.io.InputStream;
public class Test1 extends ClassLoader{
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
//name的值为com.example.demo.Test1,他是类的绝对路径
//截取name后 fileName的值为Test1.class
//加上.class表示这是个class文件
String fileName=name.substring(name.lastIndexOf(".")+1)+".class";
//加载这个class文件
InputStream input=getClass().getResourceAsStream(fileName);
//判断input是否为空
//为空就证明当前文件夹下没有这个文件
//如果为空就让父类加载器去加载它
if (input==null) {
return super.loadClass(name);
}
//如果不为空,就用当前的类加载器进行加载
try {
//简单的IO流操作,用创建一个byte数组,然后将输入流输入数组
byte [] buff=new byte[input.available()];
input.read(buff);
//方便测试,我们加上一行代码
System.out.println("自定义类加载器启动");
//当读取后,我们需要实例化class对象
//在这里我们使用java为我们提供的defineClass方法实例化对象
//defineClass的参数意思:要加载类的绝对路径,读取的数组,从第几位开始读,读到第几位结束
return defineClass(name, buff, 0, buff.length);
} catch (Exception e) {
throw new ClassNotFoundException();
}
}
}
上面我们已经完成了一个自定义类加载器,接下来使用一个方法来测试
package com.example.demo;
public class TestMain {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Test1 test1=new Test1();
//使用反射,用自定义类加载器加载并创建一个实例会对象
Object obj1=test1.loadClass("com.example.demo.TestMain").newInstance();
//使用反射,用系统默认的类加载器加载并创建一个实例会对象
Class<?> cls = Class.forName("com.example.demo.TestMain");
Object obj2=cls.newInstance();
System.out.println(obj1.getClass());
//判断obj1是否是TestMain类的实例
boolean b1=obj1 instanceof TestMain;
System.out.println("obj1是不是TestMain的实例:"+b1);
//判断obj2是否是TestMain类的实例
boolean b2=obj2 instanceof TestMain;
System.out.println("obj2是不是TestMain的实例:"+b2);
}
}
测试的结果为:

为什么obj1不是TestMain的实例?这就是回来我们一开始说道的,相同的字节码被不同的类加载器加载的类不相等。
四、自定义加载器的优势
1.高度的灵活性;
2.通过自定义类加载器可以实现热部署
3.代码加密
五、类加载器之间的协同工作--双亲委派模型
在jvm中有的各种类加载器,他们之间是通过双亲委派模型的类加载机制进行协同工作,如图:

双亲委派模型的工作原理主要是:
1)如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器完成。
2)每一层的类加载器都把类加载请求委派给父类加载器,直到所有的类加载请求都应该传递给顶层的启动类加载器。
3)如果顶层的启动类加载器无法完成加载请求,子类加载器尝试去加载,如果连最初发起类加载请求的类加载器也无法完成加载请求时,将会抛出classNotFoundException,而不再调用其子类加载器去进行类加载。
双亲委派模式的类加载机制的优点:
java类它的类加载器一起具备了一种带优先级的层次关系,越是基础的类,越是被上层的类加载器进行加载,保证了java程序的稳定运行。
深入了解java虚拟机(JVM) 第十二章 类加载器的更多相关文章
- 第十二章 类加载器&反射
12.1.类加载器 12.1.1.类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载.类的连接.类的初始化这三个步骤来对类进行初始化.如果不出现意外情况,JVM将会连续完成 ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java虚拟机学习(5):类加载器(ClassLoader
类加载器 类加载器(ClassLoader)用来加载 class字节码到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源文件在经过 Javac之后就被转换成 ...
- 《深入理解Java虚拟机》之(二、垃圾收集器与内存分配策略)
程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭,这几个区域的内存分配和回收都具备确定性,不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟着回收了,而java堆和方法区 ...
- 深入理解Java虚拟机学习笔记(二)-----垃圾收集器与内存分配策略
写在前面 本节常见面试题: 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断一个常量是废弃常量 如何 ...
- JVM体系结构之二:类加载器
一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的加载 ...
- (转)《深入理解java虚拟机》学习笔记8——Tomcat类加载器体系结构
Tomcat 等主流Web服务器为了实现下面的基本功能,都实现了不止一个自定义的类加载器: (1).部署在同一个服务器上的两个web应用程序所使用的java类库可以相互隔离. (2).部署在同一个服务 ...
- java 面向对象编程 --第十二章 JDK常用类
1. 系统类 java.lang包 System类 sys.out;sys.exit;sys.gc; sys.currentTimeMillis();----得到从1970-01-01到当前时间 ...
- 读书笔记,《深入理解java虚拟机》,第三章 垃圾收集器与内存分配策略
要实现虚拟机,其实人们主要考虑完成三件事情: 第一,哪些内存需要回收: 第二,什么时候回收: 第三,如何回收. 第二节,对象已死吗 垃圾收集其实主要是针对java堆里面的数据来说的,传统的垃圾收 ...
随机推荐
- consul service
{ "name": "consul-agent (host:{{ .MONITOR_CONSUL }})", "command&q ...
- linux sudo 系统环境变量 用户环境变量
1. sudo就是普通用户临时拥有root的权限.好处在于,大多数时候使用用户自定义的配置,少数情况可以通过sudo实现root权限做事. 故而,需要注意的一点是,在你使用了sudo后,你临时不再是原 ...
- 95. Unique Binary Search Trees II (Tree; DFS)
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...
- fbx模型动画提取教程附带一个用代码提取的方法
角色已经人形化(Humanoid)了,那它的动画可以用在其它的模型上了也就是可以共用一套模型动画了但是你有没有发现那动画是和fbx模型绑在一起的,没关系你可以选中这几个动画文件按Contrl+D就可以 ...
- 单词缩写集 · word abbreviation set
[抄题]: 一个单词的缩写根据以下的形式.下面是一些缩写的例子 a) it --> it (没有缩写) 1 b) d|o|g --> d1g 1 1 1 1---5----0----5-- ...
- React Native 常用插件案例
(二).基础入门: 1.React Native For Android环境配置以及第一个实例 2.React Native开发IDE安装及配置 3.React Native应用设备运行(Runnin ...
- [Jmeter]让报告在邮件中以链接进行显示,通过IIS
- 关于简单的三层的简化(bll,dal,model)的封装这里全部都在一个文件主要在于明白意思
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 封装泛型CRU ...
- log4j 使用记录
又很懒了.. 好久没来了,必须自我批评一下... ===========================我是分割线============================= 鼎鼎大名的log4j,要说 ...
- o7 文件和函数
一:文件 1 控制文件内指针的移动 文件内指针移动,只有在t模式下的read(n),n代表的字符的个数 除此之外文件内指针的移动都是以字节为单位的 with open('a.txt',mode ='r ...