✅P144_性能压测-性能监控-堆内存与垃圾回收
大约 3 分钟
开篇
影响性能的因素:数据库、应用程序、中间件、网络和操作系统
优化首先考虑应用属于CPU密集型还是IO密集型
一、jvm 内存模型
JVM的内存模型
1.1 程序计数器 Program Counter Register
- 记录的是正在执行的虚拟机字节码指令的地址,
- 此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError的区域
1.2 虚拟机:VM Stack
- 描述的是 JAVA 方法执行的内存模型, 每个方法在执行的时候都会创建一个
栈帧
,用于存储局部变量表
,操作数栈
,动态链接
,方法接口
等信息 - 局部变量表存储了编译期可知的各种基本数据类型、 对象引用
- 线程请求的栈深度不够会报 StackOverflowError 异常
- 栈动态扩展的容量不够会报 OutOfMemoryError 异常
- 虚拟机栈是线程隔离的, 即每个线程都有自己独立的虚拟机栈
1.3 本地方法:Native Stack
本地方法栈类似于虚拟机栈, 只不过本地方法栈使用的是本地方法
1.4 堆: Heap
几乎所有的对象实例都在堆上分配内存
二、堆
所有的对象实例以及数组都要在堆上分配。 堆是垃圾收集器管理的主要区域, 也被称为“GC堆” ; 也是我们优化最多考虑的地方。
堆可以细分为:
- 新生代
- Eden 空间
- From Survivor 空间
- To Survivor 空间
- 老年代
- 永久代/元空间
- Java8 以前永久代, 受 jvm 管理, java8 以后元空间, 直接使用物理内存。 因此,默认情况下, 元空间的大小仅受本地内存限制。
垃圾回收
从 Java8 开始, HotSpot 已经完全将永久代(Permanent Generation) 移除, 取而代之的是一个新的区域—元空间(MetaSpace)。
垃圾回收机制过程:
- 当系统产生了一个新的对象,需要为其分配内存空间,首先考虑的是在堆中的新生代(Eden)中能否放得下;如果放得下则直接存储,如果放不下则会进行一次快速的YGC;如果YGC之后还放不下则判断老年代能否放下,如果放得下则直接存储,如果放不下则会触发一次FullGC,FullGC之后还放不下则会报异常。
- YGC的过程则是判断幸存区是否能放下旧对象,如果可以放下则直接存储,每次YGC这些对象的年龄就会增加1,到15岁时就会迁移到老年代。如果放不下则判断老年代是否能放下。