JVM之基础知识

JVM之基础知识

Screen Shot 2020-09-03 at 8.50.06 PM

堆和方法区是所有线程共享的内存空间。

xmx,xms

堆是GC的主要区域,gc通常采用分代收集。

  • 新生代; eden 和两个survior
  • 老年代

大部分对象在Eden区中生成。当Eden区满时,还存活的对象会在两个Survivor区交替保存,达到一定次数的对象会晋升到老年代。 老年代用来存放从年轻代晋升而来的,存活时间较长的对象。

GC的作用区主要在方法区和堆。

方法区

存储虚拟机加载的类信息,常量,静态标量等

创建对象

  • 指针碰撞(假定内存是规整)
  • 空闲列表: 虚拟机维护一个列表,记录那些内存块是可用的

对象的内存布局

对象头,示例数据和padding

对象头包含mark word (相关 偏向锁)

如何判断对象是否存活

引用计数

可达性分析

常用,GC Roots(栈帧中的引用对象、方法区中的静态引用,方法区中的常量引用,JNI)

Post not found: JVM之引用 JVM之引用

## 垃圾回收算法

标记清除(Mark-Sweep)

Screen Shot 2020-09-03 at 10.07.29 PM

问题: 效率不高,内存碎片

复制算法

基于的假设是新生代的对象大多是朝生夕死。

将内存分为大小相同的块,每次使用其中的一块。但这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存空间的一半进行回收。但是,为了收集垃圾,将内存使用量降低为一半,成本较高。

Screen Shot 2020-09-03 at 10.10.02 PM

默认hotspot,8:1:1 、 新生代可用内存占90% (eden + 1个survior)。

如果存活大于10% ?

分配担保: 多出来的对象进入老年底。

标记整理(mark - compact)

类似于标记清清除,后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。

常见的垃圾收集器

Serial、Serial Old、ParNew、Parallel Scavenge、Parallel Old、CMS、G1。

新生代相关 (一般采用复制算法)

Serial 收集器

单线程收集器,不仅仅意味着它只会用一条垃圾收集线程去完成垃圾收集工作,重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程(“Stop The World”),直到它收集结束。

ParNew 收集器

其实就是 Serial 收集器的多线程版本,随着 CPU 的增加,可以显示出优势。 (并行

Parallel Scavenge 收集器

是一个新生代收集器,使用复制算法,并行的多线程收集器。与 ParNew 类似,但是侧重点是吞吐量( CPU 运行用户代码时间 / CPU 消耗的总时间)。可以设置参数来调整最大垃圾收集停顿时间和吞吐量的大小。

老年代

Serial Old 收集器

是 Serial 收集器的老年代版本,它同样是一个单线程收集器。

Parallel Old 收集器

是 Parallel Scavenge 收集器的老年代版本。 使用多线程和“标记-整理”算法。在注重吞吐量以及 CPU 资源配合的场合,都可以优先考虑 Parallel Scavenge 收集器和 Parllel Old 收集器。

CMS (Concurrent Mark Sweep)收集器

标记-清除算法,是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。整个过程有四个步骤:初始标记、并发标记、重新标记和并发清除。(Spark Streaming 采用这个,最少停顿)

  • 初始标记

暂停所有的其他线程,并记录下直接与 GC root 相连的对象,速度很快;

  • 并发标记

同时开启 GC 和用户线程,从GC root 继续向下进行标记,但是用户线程会继续更新对象的引用域。

  • 重新标记

重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。

  • 并发清除

开启用户线程,同时 GC 线程开始对标记的区域做清扫。

垃圾收集相关参数

SurviorRatio: 新生代中eden 和survior 比例 默认8:1

PretenureSizeTheshold: 直接晋升到老年代的对象大小阈值

MaxTenuringThreshold: 每个对象经历过一次minor GC, age加1 , 超过该阈值进入老年代

内存分配与回收策略

对象优先在eden, eden灭有足够空间minor GC

对象可直接进入老年代 - PretenureSizeTheshold:

长期存活的进入老年代 - MaxTenuringThreshold


MinorGC , FullGC, MajorGC

https://www.zhihu.com/question/41922036/answer/93079526

Partial GC:并不收集整个GC堆的模式

  • Young GC:只收集young gen的GC
  • Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式
  • Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式

Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。

young GC:eden 空间不足触发,通常有对象晋升到old gen, old gen占用上升

full GC: 准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC; 如果有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC;或者System.gc()、heap dump带GC,默认也是触发full GC。

频繁fullgc?

full gc频繁说明old区很快满了。


https://zhuanlan.zhihu.com/p/163116659

https://mp.weixin.qq.com/s/oDeO8Td-SJn9g4mRygqtSw

https://mp.weixin.qq.com/s/4oXju-Snbozg4bgOYlihcw