• 我的面试经之JVM(二)类加载器子系统ClassLoader类的加载过程


    ClassLoader,类加载器子系统:

      负责从文件系统或网络中读取class文件,class文件所在开头有特定的文件标识

      ClassLoader只负责class文件的加载,是否能运行,则由Execution Engine决定

      加载类的信息存放在一块称为方法区的内存空间。除了类的信息,方法区还可能会存放运行时常量池的信息,还可能包括字符串字面量和数字常量(这部分常量信息是class文件中常量池部分的内存映射)

    举例:

    类的加载过程:

      加载阶段:  

           1、通过类的全限定名获取定义此类的额二进制流

           2、将字节流所代表的静态存储结构转化为方法区(<7叫永久代)的运行时数据结构

           3、在内存生成一个代表此类的java.lang.Class对象,作为方法区这个类的各种数据访问入口

         加载.class方式:

                                                       

      链接(linking)阶段:      

             验证(Verify):   确保Class文件额字节流中包含的文件信息符合当前虚拟机要求,保证被加载类的正确性,不危害虚拟机自身安全

                           主要包括四种验证方式:文件格式验证、元数据验证、字节码验证、符号引用验证

             准备(prepare):  为类变量分配内存并设置该类变量为0值

                      final修饰的static不包含在内,因为这样修饰的变量就成为一个常量,编译时就会分配,这个阶段会显示初始化

                      这里不会为实例变量分配初始化,类变量会分配在方法区,实例变量会随着创建对象分配到Java堆中

             解析(Resolve): 将常量池内的符号引用转换为直接引用的过程【符号引用就是一组符号描述所引用的目标。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄

                      事实上,解析操作是在JVM初始化之后进行的  

                      解析动作主要针对类或接口、字段、类方法接口方法、方法类型等。       

      

      初始化(Initialization)阶段:

                      初始化就是执行类构造器方法<clinit>()的过程

                      此方法不用定义,由javac编译器自动搜集类中的所有类静态变量(口误没说)赋值动作和静态代码块中的语句合并而来【如果没有赋值动作或者静态代码,那么也不会有<clinit>()

                      构造器方法中指令按照在源文件中出现的顺序执行

                      <clinit>()不同于类的构造器。(关联:构造器是虚拟机视角下的<init>()方法);【任何一个类至少有一个构造器,就是init构造器】

                      若该类具有父类,JVM会保证子类的<clinit>()执行前,父类的<clinit>()执行完毕 ,如下图注释。

                                                                                                     

                      虚拟机必须保障一个类的<clinit>()方法在多线程下被同步加锁

    注意:静态代码块中可以给变量赋值,但是在声明之前不能调用,如下图:

             

  • 相关阅读:
    内置函数(少量)
    画国旗(尺寸不标准)
    测试题——程序
    乱码笔记2--字典
    列表
    课堂笔记 ——————乱
    如何利用pip安装国内镜像源
    pip常用指令
    pip卸载
    pip简介
  • 原文地址:https://www.cnblogs.com/Timeouting-Study/p/12445580.html
Copyright © 2020-2023  润新知