赞
踩
对Java 中垃圾回收相关知识,予以记录!
查看:java -XX:+PrintCommandLineFlags -version
设置:java -XX:+PrintCommandLineFlags 【垃圾回收器参数】 -version
设置某个垃圾回收器参数如下:
参考:Java JVM垃圾回收确定垃圾的两种方式,GC Root
当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(Generational Collection)的理论进行设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,它建立在两个分代假说之上:
1)弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕灭的。
2)强分代假说(Strong Generational Hypothesis):熬过越多次垃圾收集过程的对象就越难以消亡。
这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。
显而易见,如果一个区域中大多数对象都是朝生夕灭,难以熬过垃圾收集过程的话,那么把它们集中放在一起,每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象,就能以较低代价回收到大量的空间;
如果剩下的都是难以消亡的对象,那把它们集中放在一块,虚拟机便可以使用较低的频率来回收这个区域,这就同时兼顾了垃圾收集的时间开销和内存的空间有效利用。
分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。
缺点:
执行效率不稳定,如果Java堆中包含大量对象,而且其中大部分是需要被回收的,这时必须进行大量标记和清除的动作,导致标记和清除两个过程的执行效率都随对象数量增长而降低;
内存空间碎片化,标记、清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
常被简称为复制算法它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
优点:不产生内存碎片
缺点:
标记-复制算法在对象存活率较高时就要进行较多的复制操作,效率将会降低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。
标记-压缩算法其中的标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存:
缺点:
①UseSerialGC
②UseSerialOldGC(被弃用)
③UseParNewGC
④UseParallelGC
⑤UseParallelOldGC
⑥UseConcMarkSweepGC
⑦UseG1GC
源码分析:
下表图表示新生代与老年代垃圾收集器关联(重要):
G1之前的收集器特点:
以JVM参数配置与下列代码查看对应的垃圾收集器:
public static void main(String[] args) {
byte[] bytes = new byte[30 * 1024 * 1024];
}
一个单线程的收集器,在进行垃圾收集时候,必须暂停其他所有工作线程直到它收集结束。
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseSerialGC
开启后会使用Serial(Young区用) + Serial Old(Old区用)的收集器组合,新生代老年代都会使用串行回收收集器,新生代使用复制算法,老年代使用标记-整理算法
(ParNew+Tenured)
备注情况: Java HotSpot™ 64-Bit Server VM warning:Using the ParNew young collector with the Serial old collector is deprecatedand will likely be removed in a future release
(理论知道即可,实际中已经被优化了,没有了)
是Serial垃圾收集器老年代版本,同样是个单线程的收集器,使用标记-整理算法,这个收集器也主要是运行在Client默认的java虚拟机默认的老年代垃圾收集器
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseSerialOldGC
使用多线程进行垃圾回收,在垃圾收集时,会Stop-the-World暂停其他所有的工作线程直到它收集结束
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParNewGC
(ParNew+Tenured)
启用ParNew收集器,只影响新生代的收集,不影响老年代,会使用ParNew(Young区用)+ Serial Old的收集器组合,新生代使用复制算法,老年代采用标记-整理算法
备注
-XX:ParallelGCThreads:限制线程数量,默认开启和CPU数目相同的线程数
-Xms 10m -Xmx 10m -XX:+PrintGCDetails -XX:+UseParNewGC
串行收集器在新生代与老年代的并行化
类似ParNew也是一个新生代垃圾收集器,使用复制算法,也是一个并行的多线程的垃圾收集器,俗称吞吐量优先收集器。
可控制的吞吐量(Thoughput=运行用户代码时间/(运行用户代码时间+垃圾收集时间),即程序运行100分钟,垃圾收集1分钟,吞吐量就是99%)。高吞吐量意味着高效利用CPU的时间,它多用于在后台运算而不需要太多交互的任务。
自适应调节策略:虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间(-XX:MaxGCPauseMills)或最大吞吐量(这也是ParallelScavenge收集器与ParNew收集器的一个重要区别)
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelGC
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelOldGC
(PSYoungGen+ParOldGen)
备注
-XX:ParallelGCThreads=数字N 表示启动多少个GC线程
cpu>8 N = cpu数*5/8
cpu<8 N = cpu实际个数
Parallel收集器是Parallel Scavenge的老年代版本,使用多线程的标记-整理算法,Parallel Old收集器在JDK1.6才开始提供。
JVM参数:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelOldGC
(PsYoungGen+ParOldGen)
设置该参数后,新生代Parallel + 老年代Parallel Old
一种以获取最短回收停顿时间为目标的收集器,适用于互联网网站或B/S系统服务器上,希望系统停顿时间最短。CMS非常适合堆内存大、CPU核数多的服务器端应用,也是G1出现之前大型应用的首选收集器
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC
开启该参数后会自动将-XX:+UseParNewGC打开
使用ParNew(Young区用) + CMS(Old区用) + Serial Old的收集器组合,Serial Old将作为CMS出错的后备收集器
备注:
-XX:CMSFullGCsBeForeCompaction(默认0,即每次都进行内存整理,来指定多少次CMS收集之后,进行一次压缩的Full GC)
G1(Garbage-First)收集器,是一款面向服务端应用的收集器,主要应用在多CPU和大内存环境中,极大的减少垃圾收集的停顿时间,全面提升服务器的性能,在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求,逐步替换java8以前的CMS收集器
底层原理:
主要改变是Eden,Survivor和Tenured等内存区域不再是连续的了,而是变成了一个个大小一样的region,每个region从1M到32M不等。一个region有可能属于Eden,Survivor或者Tenured内存区域
区域化region区域,整体编为了一些列不连续的内存区域,避免了全内存区的GC操作
核心思想是将整个堆内存区域分成大小相同的子区域(Region),在JVM启动时会自动设置这些子区域的大小,
在堆的使用上,G1并不要求对象的存储一定是物理上连续的只要逻辑上连续即可,每个分区也不会固定地为某个代服务,可以按需在年轻代与老年代之间切换。启动时可以通过参数 -XX:G1HeapRegionSize=n 可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区
大小范围在1MB~32MB,最多能设置2048个区域,也即能够支持的最大内存为32MB * 2048 = 64G内存
G1与CMS的区别:
四步过程
JVM参数配置:
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseG1GC
- -XX:+UseSerialGC
- -XX:+UseParallelGC 或者-XX: +UseParallelOldGC
- -XX:+UseConcMarkSweepGC
- -XX:+ParNewGC
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。