• JVM的类加载机制


    一、类的加载过程

      1、加载:

        1.1、通过类的全限定名来获取类的二进制字节流。

        1.2、将字节流转换为方法区的运行时数据结构。

        1.3、在内存中生成代表该类的java.lang.Class对象,作为该类的访问入口。

      2、验证

        2.1、验证字节流是否符合Class文件规范。

        2.2、对字节码描述的语义进行分析。

        2.3、验证语义的合法性。

      3、准备

        3.1、在方法区中,为类变量(static修饰的变量)分配内存,并赋初始化值。(初始化值:根据数据的默认类型设置零值)

        初始化值举例:

          public static int value = 123;

          那么准备阶段执行完后,value = 0 。在初始化阶段,才变为 value = 123 。

      4、解析

        4.1、将常量池的符号引用替换为直接引用。

        符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要能唯一标识目标即可。

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

        举例:

          public class A{

            private List<Object> lists;

          }

        用类A的加载器,根据List的全限定名,加载List类,并将加载后的List类的访问入口,指向lists这个变量。(符号引用替换为直接引用)

      5、初始化

        5.1、初始化阶段,编译器将执行所有类变量、静态语句块的赋值动作。

        执行初始化的顺序为:

          根据语句在源文件中的先后顺序来顺序执行。先执行父类的初始化,再执行子类的初始化。

        注意:

          虚拟机会保证多线程环境下,初始化过程只能执行一次。

    二、类加载器 

      类加载器:通过类的全限定名来获取类的二进制字节流。

      类加载器分为两种:

         启动类加载器:c++语言实现,虚拟机的一部分。

         其他类加载器:继承于java.lang.ClassLoader。

      

      启动类加载器:负责将<JAVA_HOME>lib目录下的,类库加载到虚拟机中。

      扩展类加载器:加载<JAVA_HOME>libext 目录中的类,可以被开发者直接使用。

      应用程序加载器:负责加载用户类库路径(ClassPath)中的类库,可以被开发者直接使用。

      自定义类加载器:加载自定义的类库。

      双亲委派模型工作过程:

        如果一个类加载器收到了类的加载请求,它首先不会自己去尝试加载这个类,而是把这个加载请求委派给父类加载器去完成,每一个层次的类加载器都是如此。因此所有的加载请求最终都会传递到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成加载请求(在自己的搜索范围内,找不到该类)时,子类才会去尝试自己去加载。

      双亲委派模型的意义:

        1、确保唯一性。确定一个class的唯一性是由类加载器和对应的class来唯一确定的。如果不适应双亲模型,那么根类加载器和系统类加载器都加载了一个名为String的类,那么在使用的时候,值一样的对象equals就不相等。

        2、安全性。防止通过网络的形式,篡改系统库,即rt.jar。

      双亲委托模型的缺点:

        1、父加载器所加载的类,无法使用子加载器所加载的类。(解决的方法:线程上下文类加载类)

       每一个类都会使用自身的类加载器来加载所依赖的类。

      线程上下文类加载器:

        在面向接口的编程环境下,接口类是类库定义的,实现类是任意的。那么启动类加载器可以加载到接口类,但是如何识别实现类呢?此时就需要到线程上下文类加载器。

      线程上下文类加载器(Thread Context ClassLoader)。Thread类中有getContextClassLoader()和setContextClassLoader(ClassLoader cl)方法用来获取和设置上下文类加载器,如果没有setContextClassLoader(ClassLoader cl)方法通过设置类加载器,那么线程将继承父线程的上下文类加载器,如果在应用程序的全局范围内都没有设置的话,那么这个上下文类加载器默认就是应用程序类加载器(Application ClassLoader),换句话说Java默认的线程上下文类加载器就是应用程序类加载器(AppClassLoader)。

      一般使用模式:

      

    类的卸载:仅自定义加载器所加载的类,才能进行卸载。

  • 相关阅读:
    【坑】提答题
    Google Code Jam 2014 Round2
    湖北省队互测Week1
    [xyz模拟题]动态维护树的直径
    音乐会的等待【单调栈】
    51nod1202【DP-树状数组维护】
    51nod1113【矩阵快速幂】
    51nod1255【贪心-栈的应用】
    Lightoj1059【最小生成树】
    SPOJ IAPCR2F 【并查集】
  • 原文地址:https://www.cnblogs.com/chen--biao/p/9807856.html
Copyright © 2020-2023  润新知