Java ClassLoader 类加载器
ClassLoader的中文名翻译过来叫做类加载器,主要的工作就是负责把Class加载到JVM中,看起来挺高大撒上,其实就是个看大门的,只能放VIP进去,不同级别的VIP会安排到不同级别的地方,别让什么闲杂人等进JVM里面的捣乱;
虽然ClassLoader的职业比较“低下”,但是并没有阻挡人家发光发热的心,不仅可以辨认谁该进谁不该,还可以审查每个类应该由谁来加载,而且是一种父优先的等级加载机制;
还没完,人家觉悟高着呢,谁说看大门的就不能出成绩?还有第三个功能:把Class字节码重新解析成JVM统一要求的对象格式;

ClassLoader都有哪些函数?

2021-06-25-21-36-24-218182.png

ClassLoader的等级加载机制

前面说过,不同等级的VIP是必须要进入到不同的VIP接待室的,并且一个VIP去一个VIP接待室而且也只能去一次,也就是说VIP和VIP接待室是一对多的关系,还得为不知去哪里的VIP指路,同时还要防止有的VIP浑水摸鱼去更高级别的VIP接待室,如此重要的任务就落在了ClassLoader的头上,谁让咱颜值高呢,啊,不是,能力大呢!
ClassLoade是如何解决的呢?第一步:如果一个VIP到达了一个VIP接待室,那么VIP接待室会首先检查这个VIP是否已经被自己接待过,如果是,当然是拒绝,如果不是的话也不能急着放行,人家VIP并不知道自己该去哪一个VIP接待室,去级别低了掉价,去级别高了VIP接待室掉价;
第二步:向上级询问这个VIP是不是应该去级别更高的VIP接待室,那么上级也会先检查是否接待过,是的话直接拒绝并把结果反馈下去,如果不是就继续向上级的上级询问;
接着上级的上级继续重复这些检查,直到一个级别的VIP接待室说可以接待,并且也不能比他(他指的是说可以接待的)低一级的接待以及比他上一级的接待室说这个VIP级别不够,那么,这个VIP就会进入到刚才确定的VIP接待室,同时也会标记上相应的等级;
麻烦是麻烦了点,不过可以保证安全,也就是既不会让VIP掉价,也不会让VIP接待室掉价;

三种类加载器

JVM平台提供了三层ClassLoader,这三层ClassLoader又分为两种类型:
第一种:Booststrap ClassLoader(为接待室服务的接待室),这个类别人是访问不到的,必须是JVM来控制,因为它主要加载JVM自身工作需要的类,这个类是不用遵循刚才说的繁琐的规则的,仅仅就是类加载工具而已,没有父加载器也没有子加载器
第二种:AppClassLoader(为VIP服务的接待室),他的父类是ExtClassLoader,可以加载System.getProperty("java.class.path")目录下的所有的类,如果要实现自己的类加载器的话,父类必须是AppClassLoader
再说一下ExtClassLoader,他有点特殊,有点类似于与VIP接待室合作的VIP,主要加载System.getPorperty("java.ext.dirs")目录下的类;

JVM都是如何加载Class文件的?

JVM其实就是个中转站,最终代码还是交给硬件来处理,JVM把Class文件记载到内存中主要有两种方式:
第一种,隐式加载:不通过调用ClassLoader来加载需要的类,而是通过JVM来自动加载;
第二种,显式加载:也就是通过调用ClassLoader来加载;
这两种方式可以混合着使用;
那么,有一个问题,Class是怎么被加载到JVM中的?一图胜千言!
2021-06-25-21-36-24-392718.png
加载完了并不意味着工作结束了,还有验证和解析:
1. 字节码验证:类装入器对类的字节码的验证是为了保证格式正确;
2. 类准备:主要是准备好类所需要的字段、函数以及实现接口所必须的数据结构;
3. 解析:类装入器需要装入类所引用得其他类;
这些工作完成之后就可以初始化Class对象,也就是在类中包含的所有的静态初始化器都会被执行;

如何自己实现一个ClassLoader呢?

已经知道ClassLoader可以做什么了;

  1. 在自定义路径下查找自定义的Class类文件;
  2. 对于要加载的类走特殊处理,比如:加密、解密;

就这三种情况自己实现一个ClassLoader

1. 在自定义路径下查找自定义的Class类文件;

2021-06-25-21-36-24-579268.png2021-06-25-21-36-24-779681.png

2.对于要加载的类走特殊处理,比如:加密、解密;

2021-06-25-21-36-25-251419.png2021-06-25-21-36-25-450884.png

类的热部署的咋回事?

JVM在加载类之前都会调用findLoadedClass()函数来检查是否能返回类实例,同时还会判断一下一个类是否是同一个类:一个是看这个类的类名和包名是否一样,再一个就是看类加载器是否是同一个(这里主要是看实例);
2021-06-25-21-36-25-594501.png2021-06-25-21-36-25-759068.png

Java 动态加载类是最优解吗?

做Java开发的都知道java有个痛点:每修改一个类就必须重启一次;java的优势是基于共享对象这个机制的,也就是通过保存并持有对象的状态而省去类信息的重复创建和回收,如果能动态加载类了,还能实现对象的平滑过度吗?
JVM中对象只有一份,理论上可以直接替换这个对象,做起来并不难吧,JVM只要更新一下java栈中所有对原对象的引用关系就行,好了,打住!别忘了对象的引用关系只能是对象的创建者持有和使用,JVM不能干涉的,JVM只知道对象的编译时类型,对于对象的运行时类型一无所知!
那是不是就没办法了?办法还是有的,办法总比问题多嘛,可以先不保存对象的状态,对象被创建使用后就被释放掉,等到下次修改的时候,对象就是新的了,听起来是不是很耳熟?对了,这就是JSP!其实不仅仅是JSP这么做,所有的解释性语言都这样做!