Coup de Grace

爪哇虎书读后 有关gc

这本书过于基础,不适合购买

我们都知道常用GC root有几下几种;


我们又知道内存管理方式的两种方式:


我们还知道对什么进行垃圾回收:


我们后来知道HotSpot VM中GC的分类:

  1. Partial GC:并不收集整个GC堆的模式
    • Young GC:只收集young gen的GC
    • Old GC:只收集old gen的GC.只有CMS的concurrent collection是这个模式
    • Mixed GC:收集整个young gen以及部分old gen的GC.只有G1有这个模式
  2. Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式

我们早晚要知道GC的触发条件:

  1. young GC:
    当young gen中的eden区分配满的时候触发.

    注意young GC中有部分存活对象会晋升到old gen,所以young GC后old gen的占用量通常会有所升高

  2. full GC:

    • 当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC

    因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都会同时收集整个GC堆,包括young gen,所以不需要事先触发一次单独的young GC

    • 有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC
    • System.gc()、heap dump带GC,默认也是触发full GC.

并发GC的触发条件就不太一样. 以CMS GC为例,它主要是定时去检查old gen的使用量,当使用量超过了触发比例就会启动一次CMS GC,对old gen做并发收集.


标记-清除最简易模型:

分配表维护着heap内对象与数组的引用,当heap内存不够分配发生gc时:

为了避免应用运行时修改对象,gc程序需要互斥存取整个heap.此过程叫Stop-the-world.

该过程先暂停所有应用线程->垃圾回收->恢复线程.

暂停的时机叫做安全点(safepoint),通常为循环开始处或者调用起始时等等.

优化并发版本就是大名鼎鼎的CMS (concurrent mark & sweep).


下面介绍一下VisualVM与其他GC算法(复制/分代):

我们通过Visual VM手动触发一下GC

图中可见是调用了System.gc(),eden(伊甸园)内进行了清理与紧凑,可是却并没有产生到s1的复制过程. 下面我们看到eden内对象达到临界点

heap分配失败,进行gc


复制(Copy)算法过程:

  1. Eden+S0可分配新生对象
  2. 对Eden+S0进行垃圾收集,存活对象复制到S1.清理Eden+S0.一次新生代GC结束.
  3. Eden+S1可分配新生对象
  4. 对Eden+S1进行垃圾收集,存活对象复制到S0.清理Eden+S1.二次新生代GC结束.
  5. goto 1.

标记-紧凑(Mark-Compact)算法过程:

  1. 标记;标记可回收对象(垃圾对象)和存活对象.
  2. 紧凑;将所有存活对象向内存开始部位移动,称为内存紧凑.完毕后,清理剩余内存空间.

Eden/S0/S1 新生代

8:1:1 (设定方法;-XX:SurvivorRatio=8)

S0/S1是大小相当的两个区域,共同组成Survivor区

新生对象在Eden/S0或者Eden/S1中分配,Eden区的对象量达到一个阈值后,发生一次新生代GC.

Old 老年代

每个对象有”对象年龄计数器”

最大年龄阈值设定;-XX:MaxTenuringThreshold

动态年龄;如果在Survivor中所有相同年龄对象占用了空间的一半多,大于等于上述年龄的对象直接进入老年代

大对象(比如大的数组)直接进入老年代. 阈值设定;-XX:PretenureSizeThreshold.

Perm 永久代

用于存放不变对象,如类、方法、字符串等. Java7把驻留字符串(intentd string)放到了老年代区.

java8中取消了下图中的perm永久代,换为meta space本地内存.这样就吞掉了OOM产生的情况.

相对应的intellij idea配置见下图

-Xms512m
-Xmx2048m

-XX:PermSize=512m
-XX:MaxPermSize=1024m

-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=1024m

-XX:ReservedCodeCacheSize=512m
-XX:+UseCompressedOops

-server