Java虚拟机学习笔记2-垃圾收集

来源:互联网 发布:美影美视软件的教程 编辑:程序博客网 时间:2024/06/08 19:14
1.哪些对象可以被回收-根搜索算法。
2.可作为GC roots的对象有:

a.虚拟机栈帧中引用的对象

b.方法区中的类静态变量属性引用点对象

c.方法区中的常量引用的对象

d.本地方法栈中的JNI(native方法)的引用对象

3.永久代的垃圾收集:废弃常量和无用的类

废弃常量的收集:判断有木有对象引用它,没有就回收。

无用的类的收集需满足以下三个条件:a.不存在该类的任何实例;b.加载该类的classloader已经被回收;c.该类对应的java.lang.Class对象没有在任何地方被引用,无法通过反射访问该类的方法。

 

参数

-Xnoclassgc控制回不回收类

-verbose:class -XX:+TraceClassLoading,-XX:+TraceClassUnLoading查看类的加载和卸载信息

4.垃圾收集算法

标记-清除算法(最基础的算法):先标记要清除的对象,然后清除。

缺点:标记和清除两个阶段的效率不高,且容易产生内存碎片,碎片过多会导致无法找到一个连续的足够大的内存空间来分配,进而会提前触发下一次垃圾收集。

复制算法(适用于新生代,因为新生代一般来说存活的对象很少,所以需要复制的对象就少):将新生代分为3个区:1个eden,2个survivor。每次收集时将eden和一个survivor中存活的对象复制到另一个survivor,然后将前者清除。当后者的空间不足以保存所有活着的对象,可以用老年代来做分配担保(Handle Promotion)。

复制算法会浪费一个survivor的空间,且需要老年代作担保。而老年代自己本身没有谁担保,所以不能采用该算法

标记-整理算法(适用于老年代,因为老年代存活对象较多,且该算法不会像复制算法那样浪费空间):先标记,然后将存活的对象向一端移动,清理掉端外的空间。

分代收集算法:将java堆分为新生代和老年代,不同的代采用不同的算法。

5.垃圾收集器

Serial收集器:复制算法,stop the world.

一般作为client模式下新生代的默认收集器。

-XX:SurvivorRatio eden和survivor的分配比例

-XX:PretenureSizeThreshold 直接晋升老年代的对象大小

-XX:MaxTenuringThreshold晋升老年代对象年龄

-XX:HandlePromotionFailure 是否开启分配担保

ParNew收集器:复制算法,serial收集器的多线程版本,同样需要stop the world.

一般作为server模式下新生代的默认收集器。---目前只有它和serial能与CMS收集器配合工作。

-XX:ParallelGCThreads 控制垃圾收集的线程数

Parallel Scavenge收集器:新生代,复制算法,多线程,关注吞吐率(提高cpu的利用率),适合于后台运算而不需要太多交互任务的程序。

-XX:MaxGCPauseMillis控制最大垃圾收集停顿时间

-XX:GCTimeRation 控制吞吐率

上面两个参数的关系:若要想获取低停顿,必然导致低;若想获取高吞吐,必然导致每次停顿延长。

-XX:UseAdaptiveSizePolicy 自适应调节新生代大小,eden和survivor的比例,晋升老年代对象年龄等细节参数。

Serial Old收集器:老年代,标记-整理算法,

client模式默认老年代的收集器。

server模式下,两大用途:一是1.5及之前与Paraller Scavenge搭配使用。二是作为CMS收集器的后备预案,当发生Concurrent Mode Failure的时候使用。

Parallel Old收集器:Parallel Scavenge收集器的老年代版本,标记-整理算法。1.6开始提供(所以1.5之前paraller scavenge只能与serial old搭配使用)。

Parallel Scavenge/Paraller Old搭配使用,提供高吞吐率的组合。

CMS收集器:(concurrent mark sweep,并发标记清除),老年代,关注最短停顿时间,重视响应速度。应用于互联网站或B/S系统的服务端。

过程:初始标记(stop the world,仅仅标记gc roots直接关联到的对象,速度很快),并发标记(gc roots tracing),重新标记(stop the world,修正并发标记期间程序运行导致标记产生变动的那一部分对象),并发清除。

CMS无法处理浮动垃圾(在并发清理阶段,可能还会产生一部分垃圾,这部分垃圾只能在下一次清除)。即清理之前必须预留一定的空间来为用户线程运行做准备。默认情况,当老年代空间占用达到68%就触发CMS收集器收集。若预留的空间无法满足程序运行的需求,就会出现Concurrent Mode Failure.此时启用后备方案Serial Old重新进行老年代的收集。

由于采用标记清除算法,易产生内存碎片。

-XX:+UseCMSCompactAtFullCollection参数来控制是否在一次FullGC之后来一次碎片整理过程(need stop the world).

-XX:CMSFullGCFullGCsBeforeCompaction执行多少次不压缩的FullGC之后来一次带压缩的。

-XX:CMSInitiatingOccupancyFraction的值来控制空间占用多少时触发收集。

G1收集器:标记-整理算法。精确控制停顿时间(实时java的垃圾收集器特征)。可以在基本不牺牲吞吐率的前提下尽量完成低停顿。将java堆分成多个大小固定的区域,每次选择垃圾最多的区域进行收集,以获取最高的收集效率。