JavaSE知识点总结:JVM和GC篇
JVM虚拟机和GC
文档源于JDK1.8 JVM
注:图片来自网络,有版权问题请联系我删除。
1、虚拟机结构
JVM虚拟结构包括:类加载器、执行引器、运行时数据区
运行时数据区:堆、虚拟机栈、本地方法栈、pc寄存器(程序计数器)、方法区(元空间)。
- 方法区(元空间)主要用于存储运行时常量池、已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的法代码等。1.8后删除了永久代、元空间是分配到直接内存中的。
- 字符串常量池分配在堆中
- 堆内存和方法区是线程共享的,虚拟机栈、本地方法栈、程序计数器是线程独有的。
2、堆内存分代模型
- 堆分为新生代 (1/3)、老年代 (2/3)
- 新生代 = Eden+From survivor+To survivor (8:1:1)
- 堆大小 = 新生代+老年代
3、垃圾回收
- 新生代:MinorGC 也叫(YoungGC),Eden区满时触发,复制算法
- 根可达算法。Roots 指 虚拟机栈中引用的对象、方法区中类静态属性、常量,本地方法栈中java本地接口引用的对像
(复制存活对象) from eden+s1 to s2,清空s2,循环。
Suvivor空间不足,直接进入老年代 - 老年代:FullGC&MajorGC
一直未被回收的对象
老年代满了触发FGC,STW
4、垃圾回收算法
- 标记清除法–位置不连续、产生碎片
- 复制算法–没有碎片、浪费空间
- 标记压缩法–没有碎片、效率偏低
5、CMS和G1比较
CMS(Concurrent Mark-Sweep Collector)
并发标记清除收集器,它是一个多线程并发回收的老年代垃圾收集器,它使用的是标记-清除算法。
- 特点:停顿时间短,吞吐量大,并发收集
- 缺点:对cpu要求高、无法收集浮动垃圾、容易产生碎片
- 过程:初始标记>>并发标记>>重新标记>>并发清理
初始标记重新标记标记阶段会STW
hotspotGC回收器优化指南中不推荐CMS,建议使用G1
G1(Garbage First GC)
垃圾优先收集器,是一个面向服务端的JVM垃圾收集器,适用于多核处理器、大内存容量的服务端系统。
它满足短时间停顿的同时达到一个高的吞吐量。从JDK 9开始,G1成为默认的垃圾回收器。
适合场景:
- Full GC持续时间太长或者太频繁
- 对象的创建速率和存活率变动很大
- 应用不希望停顿时间长(长于0.5s甚至1s)
特点:
1、根据堆空间大小分割成了若干个Region,内存区域不连续。并且新生代和老年代的区域可以动态改变。
2、Young GC是多线程并行的,会有短暂的STW,当Eden区的空间占满之后,会触发Young GC,G1将Eden和Survivor中存活的对象拷贝到Survivor,或者直接晋升到Old Region中。
3、Old GC 当堆空间的占用率达到一定阈值后会触发Old GC。默认设置是45%。
OldGC过程:
Initial-Mark阶段和下一个Young GC一起执行,一旦Initial-Mark完成,一个多线程并行的Marking阶段开始去标记老年代所有存活的对象。当并行Marking阶段完成,一个并行的Stop-the-World的阶段开始去标记所有的对象。Remark节点结束后,G1有老年代所有Region的完整的标记信息,如果这时老年代没有任何存活对象,那么下一个阶段Cleanup阶段就不需要额外的GC工作了。
流程描述:
Initial-Mark-> Concurrent Root Region scanning->Concurrent Marking-> Remarking->Cleanup。
- 在垃圾回收的最开始有一个短暂的时间段(Inital Mark)会停止应用(stop-the-world)
- 然后应用继续运行,同时G1开始Concurrent Mark
- 再次停止应用,来一个Final Mark (stop-the-world)
- 最后根据Garbage First的原则,选择一些内存块进行回收。(stop-the-world)
Region的定义:
Available Region=可用的空闲Region
Eden Region = 年轻代Eden空间
Suivivor Region=年轻代Survivor空间
所有Eden和Survivor的集合=整个年轻代
Old Region=老年代Region
Humongous Region=大对象Region。大对象是指占用大小超过一个Region50%空间的对象
RSet(Remembered Set)
- 基于老年代的收集器采用Heap里不同区域区分/隔离对象,这些不同的区域里面的对象对应了不同年代。这样年代收集器可以集中精力在最近分配的对象上,因为它们会发现一些对象不久会死亡。这些年代在堆里可以被分别收集,这样不用扫描整个Heap,可以节省时间和减小响应时间,并且存活时间长的对象不用来回复制,减少了拷贝和引用更新开销。
- 为了方便收集器的独立性,许多GC维持了每个年代的RSet。每一个RSet是一个数据结构,它维护并跟踪收集器单元的内部引用,如G1 GC的Region一样,减少了扫描整个Heap堆获取信息的耗时。当G1 GC执行了一个Stop-the-world收集(年轻代或混合代),它可以通过CSet扫描Region的RSets。一旦存活对象被移除,它们的引用立即被更新。
- Garbage First 垃圾优先是指优先处理那些垃圾多的内存块的意思
6、JDK8默认GC
UseParallelGC 即 Parallel Scavenge + Serial Old Parallel
Scavenge 年轻代并行回收器,也叫吞量优先收集器。多线程、独占式的收集器;
特点:
- 高吞吐量。
- STW时间可设置,牺牲内存空间。
- 自适应调节内存比例。
Serial 单线程独占式GC,采用标记压缩算法。Full GC会STW
7、JVM类加载过程
- JVM的类加载机制是指虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的实现过程。
类加载过程的几个步骤:
- 加载:查找和导入二进制字节码文件。并在Java堆中创建一个该类或接口的Class对象,作为对方法区中这些数据的访问入口。
-
链接:将类的二进制代码合并到JRE中。链接过程包括验证、准备、解析三个阶段。
验证:确保二进制文件结构上的正确性。
准备:给静态变量分配内存空间并设置默认值。
解析:将常量池中的符号引用替换为直接引用的过程。 - 初始化:对类的静态变量、静态代码块执行初始化操作。