java虚拟机|JVM——类的加载过程

类的加载过程 加载过程 加载过程主要分为三个阶段:加载阶段、链接阶段、初始化阶段。
java虚拟机|JVM——类的加载过程
文章图片

  • 类加载子系统负责从文件系统或网络中加载class文件,class文件在文件开头有特定的文件标识。
  • ClassLoader只负责class文件的加载,至于它是否运行,则由(Execution Engine)执行引擎决定。
  • 加载的类的信息存放于一块称为方法区的内存空间。除了类的信息外,方法区还存放了运行时常量池信息,可能还包括字符串字面量和数字常量。
  • 常用工具:命令行:javap -v 类名.class,插件:jclasslib。
一、加载阶段 【java虚拟机|JVM——类的加载过程】加载:通过一个类的全限定名获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在内存中生成一个代表这个类的java.lang.Class对象,作为方法区中这个的各种数据结构的访问入口。
加载.class文件(字节码文件开头:CA FE BA BE)的方式
  • 从本地系统中直接加载
  • 通过网络获取,如Web Applet
  • 从zip压缩包中读取,成为日后jar,war格式的基础
  • 运行时计算生成,如动态代理技术
  • 由其他文件生成,如JSP应用
  • 从数据库中提取.class文件,少见
  • 从加密文件中获取
二、链接阶段 验证(Verify)
  • 验证class文件的字节流中包含的信息是否符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
  • 主要包含四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。
准备(Prepare)
  • 为类变量分配内存并且设置该类变量的默认初始值,即零值。
  • 不包含用final修饰的static变量,因为final在编译的时候就会分配内存,该阶段会对类变量显式初始化。
  • 这里不会为实例变量分配初始化,类变量会分配在方法区,实例变量会随着对象一起分配到Java堆中。
  • 类变量和实例变量:类变量也叫静态变量,也就是在变量前加了static 的变量,实例变量也叫对象变量,即没加static 的变量;类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象;
解析(Resolve)
  • 解析就是将常量池中的符号引用转化为直接引用。
  • 解析操作一般在JVM执行完初始化之后再执行。
  • 符号引用就是一组符号(描述所引用的目标),直接引用就是直接指向目标的指针,相对偏移量或一个间接定位到目标的句柄。
  • 解析动作主要针对类或接口,字段,类方法,接口方法,方法类型等。
三、初始化阶段
  • 初始化阶段就是执行类构造器方法clinit()的过程,此方法不需要定义,是javac编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并而来,该方法中的指令按语句在源文件中出现的顺序执行。
  • clinit()不同于类的构造器方法init()
  • 若该类具有父类,JVM会保证子类的clinit()执行之前,父类的clinit()先执行完,且保证该方法在多线程环境下被同步加锁。

    推荐阅读