开局一张图,后面曾经从每一部分解析过 JVM 的内存构造了,当初依照程序来剖析:
整体上来看:类文件从类加载子系统,加载实现之后,次要寄存在办法区(JRockit 和 H9 没有办法区,这里指的是 HotSpot)。运行时的数据次要是寄存在运行时数据区,代码的解释编译优化以及垃圾收集,都是在执行引擎中。本地办法是指 Native 办法,也就是 C /C++ 编写的办法。
类加载子系统
类文件首先须要通过类加载子系统,进行加载,进类信息等加载到运行时数据区。
在类加载子系统中有以下三个阶段操作:
- 加载
- 链接
- 初始化
其中加载的时候,有三品种加载器:
- Bootstrap ClassLoader:疏导类加载器,次要加载 JDK 外面的外围类
- Extension ClassLoader:拓展类加载器
- Application ClassLoader:利用加载器
而链接也分为 3 个阶段,次要是:
- 验证
- 链接
- 解析
运行时数据区
通过类加载子系统加载之后,进入运行时数据区,运行时区域次要分为:
-
线程公有:
- 程序计数器:
Program Count Register
, 线程公有,没有垃圾回收 - 虚拟机栈:
VM Stack
,线程公有,没有垃圾回收 - 本地办法栈:
Native Method Stack
, 线程公有,没有垃圾回收
- 程序计数器:
-
线程共享:
- 办法区:
Method Area
,以HotSpot
为例,JDK1.8
后元空间取代办法区,有垃圾回收。 - 堆:
Heap
,垃圾回收最重要的中央。
- 办法区:
虚拟机栈,每一个线程有一份,每一个线程的虚拟机栈外面,寄存的是一个个栈帧,每一个栈帧示意一个办法调用。
PC 寄存器,同样是每一个线程有一份,不同线程之间执行到何处,互不烦扰。
执行引擎
执行引擎外面能够逐行解释执行,也能够编译成机器指令间接执行,次要包含:
- 解释器
- 即时编译器:即时编译器中包含了中间代码生成器,代码优化器,指标代码生成器等。
- 垃圾收集器
解释器,须要逐行解释执行,效率低下。譬如:如果循环两千次,循环体很大,每次执行都须要解释执行。
JIT
编译器,除了能够间接全副即时编译,还能够统计出那些代码执行频率比拟高,这部分代码就是 热点代码 ,这种技术叫做 热点代码探测技术,JIT
编译器会将热点代码,提前编译成为机器指令,放在办法区缓存起来,下次执行到的时候,不须要解释执行,而是间接运行机器指令。
即时编译器的执行效率很高,为什么不将它全副提前编译好缓存起来呢?
- 全副提前编译,首次启动响应速度慢,会有卡顿的感觉,因为编译须要大量工夫。(次要起因)
- 缓存代码,须要放在办法区,占用内存空间,容易溢出。
- 翻译成为机器指令,则这部分缓存的
CodeCache
是不可能间接跨平台,因为不同环境的机器指令是不大一样的,只能每次运行前就全副编译。
如果须要写一个虚拟机,那么须要思考的重要两局部是:类加载子系统 和执行引擎 。 类加载子系统 负责将类信息依照规定,加载到运行时数据区,而执行引擎次要负责对代码解释执行或者编译成二进制缓存起来,进行执行。
【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使迟缓,驰而不息。集体写作方向:Java 源码解析,JDBC,Mybatis,Spring,redis,分布式,剑指 Offer,LeetCode 等,认真写好每一篇文章,不喜爱题目党,不喜爱花里胡哨,大多写系列文章,不能保障我写的都完全正确,然而我保障所写的均通过实际或者查找材料。脱漏或者谬误之处,还望斧正。
2020 年我写了什么?
开源刷题笔记
素日工夫贵重,只能应用早晨以及周末工夫学习写作,关注我,咱们一起成长吧~