关于Java类加载器的一些理解

Java中,每个类都可以获得对应自己类的Class对象,这是因为Object类中有public final native getClass()方法,Class对象是由类加载器根据类字节码生成的,是反射机制必不可少的部分。

类加载器中,主要的方法有protected Class loadClass(String name, boolean resolve)和protected Class findClass(String name)两个方法。

loadClass方法用来实现双亲委派机制,resolve参数用于指示是否在加载类之后立即进行解析(resolve)操作,解析是指将类的符号引用解析为直接引用,以确保类的正确链接和初始化:

复制代码
protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        //首先,检查该类是否已经加载过
        Class c = findLoadedClass(name);
        if (c == null) {
            //如果 c 为 null,则说明该类没有被加载过
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    //当父类的加载器不为空,则通过父类的loadClass来加载该类
                    c = parent.loadClass(name, false);
                } else {
                    //当父类的加载器为空,则调用启动类加载器来加载该类
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                //非空父类的类加载器无法找到相应的类,则抛出异常
            }

            if (c == null) {
                //当父类加载器无法加载时,则调用findClass方法来加载该类
                //用户可通过覆写该方法,来自定义类加载器
                long t1 = System.nanoTime();
                c = findClass(name);

                //用于统计类加载器相关的信息
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}
复制代码

findClass方法用于父加载器无法加载指定类时,子加载器本身进行加载并返回Class对象,因为ClassLoader抽象类findClass方法默认为空,接下来以AppClassLoader中的findClass方法为例:

protected Class<?> findClass(String name) throws ClassNotFoundException {
    byte[] b = loadClassBytes(name);//先加载字节码
    return defineClass(name, b, 0, b.length);//返回Class对象
}

接下来看一下loadClassBytes方法:

复制代码
private byte[] loadClassBytes(String name) throws ClassNotFoundException {
    // 将类名转换为文件路径
    String filePath = classNameToFilePath(name);

    // 读取类文件内容
    byte[] classBytes = readFileBytes(filePath);

    // 返回类字节码数组
    return classBytes;
}
复制代码

 到此可知,一般自定义类加载器继承ClassLoader,不想改变双亲委派机制的话,只要重写findClass方法,否则,则要重写loadClass

posted @   rockdow  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示