《深入理解JVM》第三章 垃圾收集器与内存分配策略(垃圾收集器)

版权声明:版权为ZZQ所有 https://blog.csdn.net/qq_39148187/article/details/81811972

垃圾回收算法是内存回收的方法论,垃圾回收器就是内存回收的具体实现,

这里讨论的是jdk1.7 之后的Hotspot 虚拟机, java 的虚拟机规范没有明确规定垃圾回收方法,因此不同的jvm 不同的版本垃圾回收是有差异的,JDK1.7 提供G1收集器,之前实在试验器

上图展示的是7 中收集器,应用的不同代,他们之间有连线的说明可以配合使用,垃圾收集器至今没有最完美的

Serial 收集器

Serial 收集器是最老的,从jdk1.3开始,收集器是单线程的,单线程不是说他只能使用一个cpu 去收集,他是指在这个收集器收集垃圾的过程中所有的线程都要停下来,这种是让人难以接受的,但是他一直还是在使用的,因为他的单线程收集在Client 模式下,桌面应用场景下,分配給jvm 的内存一般不会多大,就几百兆,Serial收集器没有线程交互的开销,专心做垃圾收集,可以获得很高的单线程垃圾回收效率,因此回收几百兆的新生代时间可控制在几十毫秒中,只要不是频繁的发生是可以接受的,所以说Serial 收集器是Client收集器的一个很好的选择

ParNew 收集器

ParNew 收集器其实就是Serial 收集器的多线程版,除了多线程之外他的控制参数,收集算法,Stop The Word 对象分配规则,回收策略和Serial 收集器是同样的,

但是他是Server 模式下虚拟机首选的新生代收集器,一个于性能无关的原因是,他能和CMS收集器配合工作,jdk1.5 期间,Hotstop推出一款在强交互的应用中几乎认为有跨时代意义的的CMS垃圾回收期(用于老年代的垃圾回收)这个款收集器是Hotstop中第一款真正意义上的并发收集器,它可以实现用户线程工作的同时,也运行,不行的是CMS收集器作为老年代的收集器他无法和jdk1.4 中的Parallel Scavenge收集器配合工作,因此在jdk1.5 选择新生代收集器的时候只能选择 ParNew 收集器和Serial 收集器的其中一种,ParNew 收集器在单CPU的情况下, 性能可能不比Serial 好,甚至由于线程交互的消耗,可能在两个cpu 的的环境都不能百分百的超过Serial 收集器,但是随着CPU增加,ParNew 收集器的性能体现就相比Serial 来说性能好,因此这也是他应用于Server 模式下的新生代收集器的原因之一,

并发 :http://ifeve.com/parallel_and_con/

并行http://ifeve.com/parallel_and_con/ 

Parallel Scavenge 收集器

也是新生代收集器,使用复制算法收集器,也是并行多线程收集器,Parallel Scavenge 收集器和parNew 收集器的关注点不同

Parallel Scavenge 收集器关注的是吞吐量, Parnew 关注的是停顿时间, Parallel Scavenge收集的目的就是达到一个可控的吞吐量,

吞吐量= 运行用户代码的时间/(运行用户代码的时间+垃圾回收的时间)

停顿时间越短 , 就越适合和用户交互的程序,提高用户的体验,而高的吞吐量可以高效的利用CPU的时间,尽快完成Cpu 的运算,主要适用于后台运算不牵扯多了线程交互,

Parallel Scavenge 提供了两个参数用于经确的控制吞吐量,-XX:MAXGCPauseMills 设置垃圾回收最大停顿时间,-XX:GCTimeRatio 设置吞吐量大小,

MaxGcPauseMills 允许的值是一个大域0 的数,但是大家不要以为这个数可以随便小,就能提高回收效率,如果设置的小,吞吐量固定;

GC停顿时间缩短,是靠新生代的内存空间取代的,如果新生代调小,那么回收i时间会缩短,但是垃圾回收的频率就会高,

由于和吞吐量有密切的关系,Paralel Scavenge 收集器也经常被称为吞吐量优先的收集器,它还提供一个参数,-XX:UseAdaptiveSizePolicy 相当于一个开关,打开之后我们就不用手动规定新生代大小比例,晋级老年代的年龄,虚拟机会根据当前系统的运作情况,性能监听信息,动态的通过这些参数调整最合适的时间和最大的吞吐量, 这种调节方式又叫做GC自动调节策略,自适应调节是Paralel  Scavenge 收集器和Par new 收集器的一个重要区别

Serial Old 收集器

看名称就知道应用老年代, 它同样是一个单线程收集器,使用标记整理算法,他主要用于Client模式下的虚拟机使用,如果用用于Server 他有两个用途,一.和Parllel Scavenge 收集器使用,二, cms 的替补,

Parallel Old 收集器

老年代,多线程,使用过标记-整理算法,这个收集器是出现在jdk1.6 因为之前,如果新生代用了Parallel Scavenge 收集器老年代无法使用CMS收集器,只能选择Serial Old 收集器,但是Serial Old 收集器是一个单线程的在server 模式中性能不是多高,这种组合还不如 Parnew 和CMS 组合,知道Parallel  Old 收集器出现,吞吐量优先的到了名副其实的组合,在注重吞吐量和CPU 敏感的场合可以使用Parallel Scavenge 和 Parlalel Old 组合实现垃圾回收,

CMS收集器

老年代,Cms 是一个以获取最短停顿收集时间的收集器,目前很大一部分用于B/S架构的网站建设中,这种收集齐很重视服务器的响应速度,给用户带来好的体验,Cms 非常符合B/S软件的需求 CMS 使用标记-清除算法,整个过程分为四部

初始化标记需要停顿,仅仅用于标记下GC Roots 能关联到的对象,速度很快,

重新标记可能需要一段比初始化标记长的时间,因为他的目的是为了修改并发标记的时候程序继续运作,导致标记变动的一些记录,

由于整个过程费时间最长的内存回收过程是和用户一起并发的,

因此他的停顿时间少,并发收集,但是CMS还没有达到完美的程度,存在一下三个问题

1.对CPU资源敏感,面向并发设计程序都对cpu资源敏感,在并发阶段,虽然他不会影响用户线程停顿,但是会使用了一部分并发线程,导致程序变慢,CMS默认启动的线程数是(CPU数量+3)/4 也就是数量在达到4个以上的时候才有25%的效率,随着cpu 增加,效率不断增加,效率都降到了50%让人无法接受的,因此虚拟机提供了一种增量并发收集齐,所做的事情和单CPU年代抢占模式多任务机制思想一样就是并发标记清理的时候让GC线程和用户线程交替执行,但是实时上ICMS这种方式效果很一般,icms 被废除,

2. cms 无法清除浮动垃圾, 由于CMS 清理垃圾的时候用户线程还是一直工作者,所以有一部分垃圾在当前这次回收是不能被回收掉的,只能等待下次回收,所以cms 不能像 其他那些收集齐使用标记整理完全的等待垃圾满了在进行清除,需要保留一部分空间提供给并发时候的程序运作使用,在jdk1.5 默认设置下, 当老年代使用68 % 的空间的时候会激活垃圾回收,这是一个保守的设置,导致cms 设置老年代的增长不是多块,可以适当通过CMSInitiatingOccupancyFraction 来提高性能的百分比,在jdk1.6中cms收集齐启动的闸值在92%如果cms 运行的时候剩余的空间无法满足就会出现一次Concurrent mode failure 失败,这时虚拟机将启动后背预案,临时使用Serial Old 收集齐来收集老年代,这样的效率变低了,如果大量的出现Concurrent mode failure 呢么性能将没有

3.cms 使用标记-清除,这样会产生大量的碎片,这些碎片将占用老年代的内存,空间碎片过多,导致没有来连续的内存,给大的对象分配地址是非常的难 ,如果无法找到足够大的连续空间区域,就会触发一次Full GC ,这个时候cms 就要进行碎片整理,内存整理的过程是没有办法并发的,

https://www.cnblogs.com/woshimrf/p/jvm-garbage.html

G1 

G1 和CMS 相比有以下优势 

http://blog.jobbole.com/109170/

理解GC日志

33.125 标识垃圾回收发生的时间,这个数字是从jvm 启动到到当前回收动作发生的时间

GC 日志开头以[GC [FULL GC 说明了这次回收的停顿类型,而不是用于区分新生代老年代,如果有FULL 说明发生了Stop the world ,如果调用System.gc() 收集,呢么这里显示[FULL GC(System)

[DefNew [Tenured [Perm 标识垃圾回收的区域,这里显示的区域名和GC 收集器有密切的关系,Serial收集器中的新生代叫做DefNew 如果是ParNew 新生代叫做ParNew 如果采用Parallel Scavenge 他的新生代叫做PSYoungGen老年代(和永久代)同样,

后方方括号外的 3324K->152K(3712K)含义是 Gc前java堆内存的容量->GC后java 堆的使用容量(java堆的总容量)再往后就是时间,

-XX:+PrintGCTimeStamps:

打印此次垃圾回收距离jvm开始运行的所耗时间

-XX:+PrintGCDeatils

打印垃圾回收的细节信息

-Xloggc:<filename>

将垃圾回收信息输出到指定文件

-XX:+PrintGCDateStamps

需要打印日历形式的时间戳选项

-XX:+PrintGCApplicationStoppedTime

-XX:+PrintGCApplicationConcurrentTime

打印应用程序由于执行VM安全点操作而阻塞的时间以及两个安全点操作之间应用程序的运行时间

-XX:+PrintSafepointStatistics

可以将垃圾回收的安全点与其他的安全点区分开

猜你喜欢

转载自blog.csdn.net/qq_39148187/article/details/81811972
今日推荐