深度解析类加载机制

1、类加载宏观图:

流程(宏观)

2、ClassLoader.loadClass() 关键流程:

loadClass

  • 加载:在磁盘上查找并通过io读入字节码文件;将字节流所代表的静态存储结构转化为方法区的运行时数据结构;在内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据的访问入口
  • 验证:1、文件格式验证:验证字节流是否符合Class文件格式的规(如:.class文件开头为CAFE BABE),并且能够被当前虚拟机处理。2、元数据验证:内容是否符合JVM规定。3、字节码验证:验证字节码文件方法中的Code结构,就是验证所编写的方法是否正确合理。(语法校验等)。4、符号引用验证:JVM将符号引用转化为直接引用的时候校验。该阶段会把一些静态方法(符号引用,比如main()替换为指向数据所存内容的指针或句柄等)也叫静态链接
  • 准备:为类的静态变量分配内存并设置初始值,在这个阶段把这些变量所使用的内存在方法区进行分配
  • 解析:JVM将常量池内的符号引用替换为直接引用的过程
  • 初始化阶段:就是执行类构造器()方法的锅成功。常量赋值、静态代码块直径过程。(准备阶段是对常量设置初始值,这里是对常量设置我们自己定义的值)

验证、准备、解析通称为链接过程
类被加载到方法区后主要包含运行时常量池、类型信息、字段信息、方法信息、类加载器的引用(这个类到类加载器实例的引用)、对应class实例的引用等信息(类加载器在加载类信息放到方法区后,会创建一个对应的Class类型的对象实例放到堆中,作为开发人员访问方法区中类定义的入口和切入点),主类在运行过程中如果使用到其他类,会懒加载

3、类加载器:

  • 引导类加载器:负责加载支持JVM运行的,位于JRE的lib目录下的核心类库,如:rt.jar等(由于引导类加载器是使用C++语言实现的,当我们调用getClassLoader时会返回NULL,属于正常现象)
  • 扩展类加载器:负责加载支持JVM运行的,位于JRE的lib目录下EXT扩展目录中的JAR
  • 应用程序类加载器:负责加载ClassPath路径下的类包,主要是加载我们自己应用程序的类
  • 自定义类加载器:负责加载用户自定义路径下的包
    双亲委派
    优点:
  • 沙箱安全机制:防止一些java核心的类,如String、Long被篡改
  • 避免重复的类加载:当父亲已经加载了该类时,子classLoader就没有必要再加载一次了,保证被加载类的唯一性
    源码分析:
    //实现自定义类加载器也非常简单
    //思路:查看AppClassLoader 源码,跟着写
    static class AppClassLoader extends URLClassLoader
    public class URLClassLoader extends SecureClassLoader implements Closeable 
    public class SecureClassLoader extends ClassLoader
    //通过追踪我们发现继承了 ClassLoader 这个抽象类,并重写了loadClass这个方法
    public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
            int var3 = var1.lastIndexOf(46);
            if (var3 != -1) {
                SecurityManager var4 = System.getSecurityManager();
                if (var4 != null) {
                    var4.checkPackageAccess(var1.substring(0, var3));
                }
            }

            if (this.ucp.knownToNotExist(var1)) {
                Class var5 = this.findLoadedClass(var1);
                if (var5 != null) {
                    if (var2) {
                        this.resolveClass(var5);
                    }

                    return var5;
                } else {
                    throw new ClassNotFoundException(var1);
                }
            } else {
                //直接看return
                return super.loadClass(var1, var2);
            }
        }
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            //首先,检查该类是否已经加载
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    /*
                    * 核心代码:如果父类不为null,则调用分类的loadClass
                    * parent为属性
                    */
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // 如果找不到类,则抛出ClassNotFoundException
                }

                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;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值