黑马程序员技术交流社区

标题: 【上海校区】JVM 类加载机制 [打印本页]

作者: 孤尽    时间: 2019-4-27 13:48
标题: 【上海校区】JVM 类加载机制
本帖最后由 孤尽 于 2019-4-27 13:51 编辑

JVM 类加载机制

摘要: jvm将描述java类的.class的字节码文件加载到内存中,并对文件中的数据进行安全性校验、解析和初始化,最终形成可以被java虚拟机直接使用的java类型,这个复杂的过程为jvm的类加载机制 类从被java到虚拟机内存开始,直到被卸载出内存为止,整个生命周期如上图所示,分为:加载、验证、准备、解析、初始化、使用、卸载共7个阶段。

    jvm将描述java类的.class的字节码文件加载到内存中,并对文件中的数据进行安全性校验、解析和初始化,最终形成可以被java虚拟机直接使用的java类型,这个复杂的过程为jvm的类加载机制

类从被java到虚拟机内存开始,直到被卸载出内存为止,整个生命周期如上图所示,分为:加载、验证、准备、解析、初始化、使用、卸载共7个阶段。

class类的初始化时机
虚拟机规范严格规定,有且只有5种情况,必须立即对类进行初始化:
这两种情况不会进行类的初始化
[Java] 纯文本查看 复制代码
public class Test {
    public static void main(String[] args) {
        System.out.println(B.value);
    }
}

class A {
    public static int value = 123;
   
}

class B extends A {
   
}


类加载的过程加载

在加载阶段,虚拟机需要完成以下3件事情:
连接
连接是很重要的一步,过程比较复杂,分为三步 验证 》准备 》解析   
初始化jvm类加载器
虚拟机设计团队把加载动作放到JVM外部实现,以便让应用程序决定如何获取所需的类,实现这个动作的代码模块称为“类加载器”。JVM提供了3种类加载器:
JVM通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader实现自定义的类加载器。
类加载器加载的class在堆内存中的模型:

认识双亲委派模型
对于某个特定的类加载器而言,应该为其指定一个父类加载器,当用其进行加载类的时候:
请注意:
双亲委派模型中的"双亲"并不是指它有两个父类加载器的意思,一个类加载器只应该有一个父加载器。上面的步骤中,有两个角色:
双亲模型如下图:
AppClassLoader的工作流程如下图:
双亲委派模型底层代码实现:
[Java] 纯文本查看 复制代码
//提供class类的二进制名称表示,加载对应class,加载成功,则返回表示该类对应的Class<T> instance 实例
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

   
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,检查是否已经被当前的类加载器记载过了,如果已经被加载,直接返回对应的Class<T>实例
            Class<?> c = findLoadedClass(name);
                //初次加载
                if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        //如果有父类加载器,则先让父类加载器加载
                        c = parent.loadClass(name, false);
                    } else {
                        // 没有父加载器,则查看是否已经被引导类加载器加载,有则直接返回
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                // 父加载器加载失败,并且没有被引导类加载器加载,则尝试该类加载器自己尝试加载
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    // 自己尝试加载
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            //是否解析类
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

如何破坏双亲委托模型:







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2