java类加载过程

类的生命周期

java类加载过程_第1张图片

前面三步:加载 连接 初始化 将Class文件加载到虚拟机中

加载:
1、通过全类名定义获取此类的二进制字节流
2、将字节流所代表的静态存储结构转换为方法区的运行时数据结构
3、在内存中生成一个代表该类的Class对象,作为方法区这些数据的访问入口

每个java类都有一个引用指向加载它的ClassLoder

准备:
为类变量分配内存并设置类变量初始值

解析:
虚拟机将常量池的符号引用替换为直接引用的过程

什么是符号引用:
符号引用以一组符号来描述所引用的目标

什么是直接引用:
直接引用是可以直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄

初始化:
初始化阶段是执行初始化方法的过程,是类加载的最后一步

类卸载:卸载类即该类的Class对象被GC

类加载器

加载java类的字节码(.class文件)到JVM中

字节码可以是.java文件经过javac编译得到 也可以通过工具动态生成、通过网络下载得来

加载规则:先判断该类是否被加载过,已经加载的类直接返回

内置加载器:
1、BootstrapClassLoader – 启动类加载器
加载JDK内部的核心类库

2、ExtensionClassLoader – 扩展类加载器
加载ext目录下的jar包和类

3、AppClassLoader – 应用程序类加载器
负责加载当前应用classPath下的所有jar包和类

自定义类加载器
需要继承java.lang.ClassLoader
关键方法:
1、proteceted Class loadClass(String name,boolen resolve)
加载指定二进制名称的类,实现双亲委派机制

2、protected Class findClass(String name)
根据类的二进制名称来查找类

什么是双亲委派模型?
每个ClassLoader实例都有一个相关的父类加载器,ClassLoader实例会在试图亲自查找类或者资源之前,将搜索类或资源的任务委托给其父类加载器

ClassLoader的loadClass()方法

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) {
            //对类进行link操作
            resolveClass(c);
        }
        return c;
    }
}

双亲委派模型的好处:避免类的重复加载

你可能感兴趣的:(java,web后端,java,jvm,开发语言)