JVM:JVM初始化以及内存区域划分

154 阅读2分钟

JVM是怎样初始化的?

JVM的初始,将class文件解析的过程。分为7个步骤

  • 加载
  • 验证
  • 准备
  • 解析
  • 初始化
  • 使用
  • 卸载

加载阶段:点击程序运行

验证阶段:检测 .class 文件是否符合规范,是否被篡改

准备阶段:给每个写好的类分配一定的内存空间、给变量分配默认值

解析阶段:把符号应用替换为直接引用

  • 符号引用:定位到目标的一种符号
  • 直接引用:直接或间接指向目标,定位到目标

初始化阶段:给变量进行赋值(和准备阶段不同,准备阶段仅仅是赋值默认值)

贴一张图感受一下

在初始化阶段如果检测到 A 这个类存在父类,必须先加载、初始化这个父类。就会有类加载器的概念

类加载器

类加载器有4种

  • 启动类加载器
  • 扩展类加载器
  • 应用程序类加载器
  • 自定义类加载器

双亲委派机制

类加载的时候会存在类继承关系,会先加载父类,从上而下依次加载,如果父类无法完成这个任务,那么子加载器就需要自己完成加载。

JVM内存区域划分

  • 方法区:存变量、方法、类(方法区在JDK1.8之后变成了MetaSpace(元空间))

  • 字节码执行引擎:用来执行放在方法区里的内容

  • 程序计数器:记录执行字节码指令的位置

  • java虚拟机栈:用来存放执行方法时的局部变量

  • java堆内存:存放实例之后的对象、变量

思考:为什么要记录指令位置?

因为程序可能是多线程执行的,所以要记录执行到哪个地方,并且每个线程都存在一个程序计数器

扩展一下java堆内存

其中有一块永久代,在JDK1.8之后也变成了 MetaSpace(元空间)

思考:永久带和方法区有什么关系,永久代=方法区吗

GC分代收集扩展至方法区,也可以说永久代实现了方法区。永久代是一种概念实现,方法区是一种定义规范。个人认为不用太过纠结,也可以直接看作永久代=方法区。

总结:

class文件会被加载到方法区中,字节码执行引擎会执行方法区中的内容,程序计数器会记录执行的位置,经过虚拟机栈进入堆内存