JVM知识串联

目标

读完周志明老师《深入理解Java虚拟机》之后,觉得需要将书读薄,将里面的知识融会贯通。所以以一个Class的生命周期作为角度重新整理知识,有一个完整的认知。

生命周期

  1. 编译:将java源代码经过编译器编译成符合class文件规范的二进制class文件。
  2. 加载:按照一定的初始化的规则顺序,进行加载、验证、准备、解析和初始化的过程,将类加载到方法区,完成类的定义加载到虚拟机。
  3. 实例化:使用new命令进行实例化对象,按照之前加载的类进行分片空间,将对象分配到堆。
  4. 执行:根据命令执行执行,其中方法调用涉及多态的选择,涉及程序计数器和虚拟机栈的使用。
  5. 收集:在命令的执行会产生很多对象分布在JVM内存中,会根据不同的策略进行收集。

编译

将java源码代码编译成符合class文件规范的二进制class文件。而class文件的格式如下

ClassFile {
 u4 magic;
 u2 minor_version;
 u2 major_version;
 u2 constant_pool_count;
 cp_info constant_pool[constant_pool_count-1];
 u2 access_flags;
 u2 this_class;
 u2 super_class;
 u2 interfaces_count;
 u2 interfaces[interfaces_count];
 u2 fields_count;
 field_info fields[fields_count];
 u2 methods_count;
 method_info methods[methods_count];
 u2 attributes_count;
 attribute_info attributes[attributes_count];
}

加载

将class文件按照初始化的触发条件通过类加载器进行加载。

初始化的条件

  1. 执行new 、getstatic、putstatci、invokestatic指令
  2. 反射调用
  3. 类存在父类,父类先初始化,接口不需要
  4. 启动需要执行的主类
  5. JDK7中,MethodHandle解析结构REF_getStatic、REF_putStatic、REF_invokeStatic
  6. JDK8中,定义接口的默认方法,如果实现类发生初始化,则接口先初始化

加载的生命周期

  1. 加载:将class文件加载到方法区和运行时常量池,存储类的常量池、字段和方法和一些特殊方法
  2. 链接

    1. 验证:验证class文件是否符合规范的文件
    2. 准备:创建类或接口的静态变量,并且赋予默认值
    3. 解析:根据运行时常量池的符号引用决定具体的方法
  3. 初始化:初始化类变量和其他资源
解析的过程不一定在准备之后,也可能发生运行时进行解析,比如多态的使用

实例化

通过new命令进行实例化,实例化之后的对象不仅仅是定义的类的结构,也存在一些用于收集和并发控制的需要的信息,然后在堆内按照一定的约定在不同的区域进行分配。

对象组成

  1. 对象头

    1. 哈希码
    2. GC分代年龄
    3. 锁状态标志
    4. 线程持有的锁
    5. 偏向线程ID
    6. 偏向时间戳
    7. 类型指针
  2. 实例数据
  3. 对齐填充

对象存储位置

  1. 大多数对象直接分配到Eden区
  2. 大对象(需要大量连续内存)分配到Tenured区
  3. 对象在Survivor区熬过一次新生代GC年龄增加1,当增加到15,存储在老年代
  4. Survivor空间相同年龄的所有对象大小总和大于Survivor的一半

执行

根据class文件解析之后的命令使用虚拟机栈和程序计数器进行执行,其中会存在方法多态的一个解析。

虚拟机栈组成

  1. 局部变量表:方法入参,局部变量
  2. 操作数栈:用于执行存储执行命令需要的参数
  3. 动态链接:指向运行时的常量池的引用
  4. 方法返回地址

收集

JVM中的内存不同区域会在不同的情况下会进行不同的收集。

收集堆

  1. Eden区空间不能进行分配会进行MinorGC,将存活的对象存储在Survivor区
  2. Survivor区对象年龄达到MaxTenuringThreshold值会存储在Tenured区
  3. Survivor区相同年龄的所有对象大小总和大于Survivor区空间的一半,大于等于该年龄的对象进入Tenured区
  4. MinorGC进行空间分配担保,如果Tenured区的可用的连续空间小于晋升Tenured区平均大小,则进行FullGC,如果大于,同时HandlePromotionFailure为true,则进行冒险MinorGC,如果还是不够则进行FullGC
  5. Tenured区空间不够,会先进行MinorGC,如果空间还是不足则进行MajorGC

收集方法区

  1. 没有进行引用的常量,则收集
  2. 收集类型

    1. 该类下的所有实例已经被回收
    2. 加载改类的类加载器被回收
    3. 类的class对象没有被引用

你可能感兴趣的:(jvm)