一、什么是类加载器

  类加载器是一个用来加载类文件的类,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) 第十二章 类加载器的更多相关文章

  1. 第十二章 类加载器&反射

    12.1.类加载器 12.1.1.类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载.类的连接.类的初始化这三个步骤来对类进行初始化.如果不出现意外情况,JVM将会连续完成 ...

  2. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. Java虚拟机学习(5):类加载器(ClassLoader

    类加载器 类加载器(ClassLoader)用来加载 class字节码到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源文件在经过 Javac之后就被转换成 ...

  4. 《深入理解Java虚拟机》之(二、垃圾收集器与内存分配策略)

    程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭,这几个区域的内存分配和回收都具备确定性,不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟着回收了,而java堆和方法区 ...

  5. 深入理解Java虚拟机学习笔记(二)-----垃圾收集器与内存分配策略

    写在前面 本节常见面试题: 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断一个常量是废弃常量 如何 ...

  6. JVM体系结构之二:类加载器

    一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的加载 ...

  7. (转)《深入理解java虚拟机》学习笔记8——Tomcat类加载器体系结构

    Tomcat 等主流Web服务器为了实现下面的基本功能,都实现了不止一个自定义的类加载器: (1).部署在同一个服务器上的两个web应用程序所使用的java类库可以相互隔离. (2).部署在同一个服务 ...

  8. java 面向对象编程 --第十二章 JDK常用类

    1.  系统类 java.lang包   System类 sys.out;sys.exit;sys.gc; sys.currentTimeMillis();----得到从1970-01-01到当前时间 ...

  9. 读书笔记,《深入理解java虚拟机》,第三章 垃圾收集器与内存分配策略

    要实现虚拟机,其实人们主要考虑完成三件事情: 第一,哪些内存需要回收: 第二,什么时候回收: 第三,如何回收. 第二节,对象已死吗    垃圾收集其实主要是针对java堆里面的数据来说的,传统的垃圾收 ...

随机推荐

  1. 通过nginx + lua来统计nginx上的监控网络请求和性能

    介绍 以前我们为nginx做统计,都是通过对日志的分析来完成.比较麻烦,现在基于ngx_lua插件,开发了实时统计站点状态的脚本,解放生产力. 项目主页: https://github.com/sky ...

  2. Shadow Mapping 的原理与实践 【转】

    早在上世纪七十年代末,Williams在他的“Casting Curved Shadows on Curved Surface”一文中提出了名为Shadow Map的阴影生成技术.之后,他人在此基础上 ...

  3. Swift与OC的相互调用

    Swift经过四年的发展已经趋于成熟,是时候学一下了,感谢公司swift大佬的不吝赐教.心有所感记录一下,如有不足欢迎指正批评. 新建swift项目 新建Swift.OC类文件 可在新建OC文件时,建 ...

  4. 图是否是树 · Graph Valid Tree

    [抄题]: 给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向边的列表 (给出每条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树. 给出n = 5 并且 edges = ...

  5. Shadow Map 实现极其细节

    这里不介绍算法原理,只说说在实现过程中遇到的问题,以及背后的原因.开发环境:opengl 2.0  glsl 1.0. 第一个问题:产生深度纹理. 在opengl中每一次离屏渲染需要向opengl提供 ...

  6. Trait 概览

    Trait是PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait ...

  7. 不要怂,就是GAN (生成式对抗网络) (三):判别器和生成器 TensorFlow Model

    在 /home/your_name/TensorFlow/DCGAN/ 下新建文件 utils.py,输入如下代码: import scipy.misc import numpy as np # 保存 ...

  8. 动态列 Excel 导出

    /// <summary> /// 导出数据通用属性 需在属性进行标记 /// </summary> [AttributeUsage(AttributeTargets.Clas ...

  9. Gym 101201F Illumination (Two-Sat)

    题意:一个n*n的房子,有很多灯,每个格子只能被上下方向照一次.左右方向照一次,每个灯可以选择上下或是左右照,照明长度以自身位置为中心,占用2*r+1个格子.问能否安排一种方案,使所有格子满足条件. ...

  10. Linux下的用户权限

    用户权限: drwxr-xr-x root root - : boot #权限位 硬连接数 所属用户 所属组 大小 最后修改时间 文件/目录# r w x 4 2 1 用户权限位分为3段,分别对应US ...