• jvm 类和类加载器 、双亲委派模型、自定义类加载器



    1. 类和类加载

      类加载器虽然只用于实现类的加载动作,但在java程序中作用却远不止如此。任意一个类都由类加载器和类本身确定其在java虚拟机中的唯一性。每个类加载器拥有一个独立的类名称空间。

    如:

    package com.cz.core.rdd;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class T33 {
        public static void main(String[] args) {
            ClassLoader classLoader = new MyClassLoader();
            try {
                Object o = classLoader.loadClass("com.cz.core.rdd.T33").newInstance();
                System.out.println(o.getClass());
                System.out.println(o instanceof T33);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    
    class MyClassLoader extends ClassLoader {
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
    
            try {
                String filename = name.substring(name.lastIndexOf(".") + 1) + ".class";
                InputStream resource = getClass().getResourceAsStream(filename);
                if (resource == null) {
                    return super.loadClass(name);
                }
                byte[] bytes = new byte[resource.available()];
                resource.read(bytes);
                return defineClass(name, bytes, 0, bytes.length);
            } catch (IOException e) {
                throw new ClassNotFoundException(e.getMessage());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

      代码中自定义类加载器MyClassLoader 加载类T33 和采用系统默认的类加载器加载类T33 是完全不同的。即便2个类来源于同一个Class文件,被同一虚拟机加载,只要加载的类加载器不同,两个类必然不相等(包括类的Class对象的equals()、isAssignableFrom()、isInstance()以及instanceof关键字判断对象的所属关系)。上述代码中虚拟机存在2个T33 类,一个是由自定义的类加载器加载,另一个是由系统应用程序类加载器加载的。打印2个类的类加载器内存地址即com.cz.core.rdd.MyClassLoader@7aec35asun.misc.Launcher$AppClassLoader@18b4aac2


    2. 双亲委派模型

      从java虚拟机的角度看,存在2种不同的类加载器:
    (1)启动类加载器 Bootstrap ClassLoader
      使用C++语言实现,作为虚拟机自身的一部分。这个类加载器负责将存放在 JAVA_HOME下lib目录中的或者被-Xbootclasspath参数所指定的路径中的,并且被虚拟机识别的(仅按照文件名识别,如rt.jar)类库加载到虚拟机内存中。启动类加载器无法被java程序直接引用
    (2)所有其他的类加载器
      全部由java语言实现,独立于虚拟机的外部,全部继承自抽象类java.lang.ClassLoader,有以下三类:
    扩展类加载器(Extension ClassLoader):负责加载JAVA_HOME下lib\ext目录中的或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可直接使用扩展类加载器

    应用程序类加载器(Application ClassLoader):这个类加载器是ClassLoader中getSystemClassLoader()方法的返回值,一般称之为系统类加载器。负责加载用户类路径(ClassPath)上所指定的类库。开发者可直接使用应用程序类加载器,一般情况下,应用程序没有自定义类加载器,这个就是默认的类加载器

      如果有必要,可加入自定义的类加载器
    在这里插入图片描述
      如上图所示类加载器双亲委派模型(除了顶层的启动类加载器,其余加载器均有自己的父类加载器。加载器之间的父子关系一般不会以继承关系来实现,而是通过组合关系来复用父加载器的代码)
    在这里插入图片描述

      其工作过程是:如果一个类加载器收到类加载的请求,首先不会自己去尝试加载这个类,而是把这个请求委派给给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都会传送给顶层的启动类加载器,只有当父类加载器反馈自己无法加载这个请求(它的搜索范围内没有找到所需的类),子类才会尝试加载。双亲委派模型使得java类具有一种带有优先级的层级关系。如java.lang.Object,存放在rt.jar中,无论哪个类去加载,最终都是委派给模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类,反之不使用双亲委派模型,会造成系统存在多个Object类出现混乱。


  • 相关阅读:
    wangEditor富文本编辑器使用
    在 UltraEdit 和 UEStudio 中开始使用 Perl 正则表达式
    pycharm 里面安装 codeium 插件的时候,不能够弹出登录界面
    【笔记】判断高电平,低电平和方波的几种方法
    短视频引爆销售:TikTok如何改变跨境电商游戏规则
    Java中对date数据做加减时间运算——Calendar类
    【Python刷题篇】——Python入门 011面向对象(一)
    一个分布在多次Softmax后,会趋于相同
    TCP的延时应答和捎带应答详解
    【蓝桥备战】DFS、BFS
  • 原文地址:https://blog.csdn.net/javahelpyou/article/details/126241829