虚拟机类加载机制

2019-02-20  本文已影响0人  油多坏不了菜

概述

虚拟机把描述类的数据从Class文件加载到内存,对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,此为虚拟机的类加载机制。

一、类加载的时机

二、类加载的过程

2.1 加载

 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);

2.2验证

2.3准备

为类变量分配空间,并设置初始值。通常初始值为零,除了常量:被final和static修饰的(编译时 通过ConstantValue属性设值)。

2.4解析阶段

符号引用替换为直接引用的过程

2.5初始化

三、类加载器

3.1 类与类加载器

类的唯一性由加载他的 类加载器和 这个类本身一同确定

3.2 双亲委派模型

  1. 启动类加载器(Bootstrap ClassLoader),使用C++实现,加载<JAVA_HOME>\lib目录中,或者被-Xbootclasspath参数指定的路劲中的文件(按名字识别,如rt.jar)
  2. 启动类加载器无法被Java程序直接引用,如果需要把加载请求委托给启动类加载器,则直接使用null代替。
  3. 扩展类加载器,负责加载<JAVA_HOME>\lib\ext目录中的文件,ExtClassLoader可以被开发者直接使用。
  4. 应用程序加载器(AppClassLoader),由ClassLoader中的getSystemClassLoader方法返回,负责加载用户类路劲(classpath)上的所有类库
  5. 工作流程: 类加载器收到类加载请求时,首先把请求委托给父类(这里用的组合的方式),只有父类无法完成类加载时,才自己去加载类。
  6. 双亲委派模型这种层级关系可以保证如Object类只被引导类加载。
  7. 双亲委派模型代码
 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            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;
        }
    }
上一篇下一篇

猜你喜欢

热点阅读