JVM基础思维导图(持续更新中)
JVM
JVM内部构造
字节码执行引擎
- 任务就是将字节码指令编译为对应平台上的本地机器指令执行
JVM内存模型
内部关系
-
程序计数器
-
存在位置:每个线程都占有的独立的内存区域中,都有一部分区域用来放该线程的程序计数器
- .class文件 (java -c 得到)
-
字节码文件中,每个方法对应的解析后内容
Code: 0 - n 就是我们想要的那个执行位置
(行数)
- 用处:用于记录当前线程正在执行的代码的位置(行号)
- 存在原因:假如CPU执行该线程到一半去干别的活,当前线程被挂起,那么就需要知道被插队前执行到哪了,以方便CPU回来干活后能从上一个记录点继续
- 数值变化:每运行完一行,程序计数器存放的值会被字节码执行引擎修改
-
方法区(元空间,永久代)
- 存放内容:
常量,静态变量,类信息
- 存放内容:
-
本地方法栈
- 本地(native)方法专用的内存空间:
当调用native修饰的方法,即使用C语言编写的底层方法时,JVM会在该线程的内存空间内划出一块区域给它
-
线程栈
-
每条线程在开始运行前,JVM都会为该线程分配独立的栈内存空间存放局部变量
- 栈帧内存:
在一条线程内,当要执行某个方法时,JVM会在其所拥有的栈内存空间内,为这个方法分配其独立的内存空间存放局部变量(套娃)。
- 栈帧内存:
-
当该方法调用完成后,方法所占的栈帧内存被释放。
栈内存顺序(FILO):程序方法嵌套调用与栈的结构相同
- 栈帧内存内部:
-
局部变量表
-
操作数栈
-
动态链接
-
方法出口
- 局部变量表:
是变量值的存储空间,由方法参数和方法内部定义的局部变量组成,其容量用Slot1作为最小单位
- 操作数栈:
LIFO栈,由字节码指令往栈中存数据和取数据
- 动态链接:
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有该引用是为了支持方法调用过程中的动态连接。
- 方法出口:
存放调用调用该方法的pc计数器的值。当一个方法开始之后,只有两种方式可以退出这个方法:
1、执行引擎遇到任意一个方法返回的字节码指令,也就是所谓的正常完成出口。2、在方法执行的过程中遇到了异常,并且这个异常没有在方法内进行处理,也就是只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种方式成为异常完成出口。
正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的不会给他的上层调用者产生任何的返回值。
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置,方法正常退出时,调用者的pc计数器的值作为返回地址,而通过异常退出的,返回地址是要通过异常处理器表来确定,栈帧中一般不会保存这部分信息。
- 存放堆中对象的内存地址
-
堆
-
存储:
new的对象 -
堆的内部结构
-
年轻代
-
Eden区
-
当Eden区满了以后, Minor GC前来收垃圾
- 收垃圾原理
-
-
Survivor区
- From区
- To区
-
-
老年代
-
老年代满了以后,Full GC前来收垃圾
- Full GC结束工作后还是没位置,发生OOM
-
-
-
-
Tips:
-
堆和方法区是被线程共享的区域
-
堆内存大小分配:
年轻代:
Eden : From: To = 8 : 1 : 1 -
从Survivor区进入老年代区:
-
- 长期存活:分代年龄达到15
- 对象动态年龄判断:非垃圾对象大小大于即将进入的Survivor区的1/2
- 大对象:(字符串,数组等)JVM参数可以设置大对象大小,超过该阀值则直接进入老年代
JVM调优
JVM调优目的
-
减少用户的停顿时间
-
减少STW时间
- 减少Full GC次数
-
References:
- 2020年最新Java虚拟机JVM底层原理分析视频教程全集 — 程序员诸葛
Retrieved from: https://www.bilibili.com/video/BV1dJ411G7YJ?p=7 - Java JVM 中 堆,栈,方法区 详解 — 张启露
Retrieved from: https://blog.csdn.net/zhangqiluGrubby/article/details/59110906