005 jvm_垃圾收集算法、垃圾收集器详解

1.虚拟机模式

        目前java虚拟机支持Client和Server两种运行模式,在jdk1.7以后应用的基本都是server模式,使用参数-client可以指定使用Client模式,使用-server即使用Server模式。可以直接在命令行查看当前计算机系统自动选择的运行模式。java -version即可。
        二者区别:Client模式相对Server启动较快,如果不追求系统的长时间使用性能仅仅是测试,可以使用Client模式。而Server模式则启动比较慢,原因是会对其进行复杂的系统性能信息收集和使用更复杂的算法对程序进行优化,一般我们的生产环境都会使用Server模式,长期运行其性能要远远快于Client模式。

2.垃圾收集器

        垃圾回收(Garbage Collection,简称GC),需要先澄清什么是垃圾,类比日常生活中的垃圾,我们会把他们丢入垃圾桶,然后倒掉。GC中的垃圾,特指存于内存中、不会再被使用的对象,而回收就是相当于把垃圾“倒掉”。
垃圾回收有很多种算法:如引用计数法、标记压缩法、复制算法、分代、分区的思想。

引用计数法:这是个比较古老而经典的垃圾收集算法,其核心就是在对象被其他所引用时计数器加1,而当引用失效时则减1,但是这种方式有非常严重的问题,无法处理循环引用的情况、还有就是每次进行加减操作比较浪费系统性能。(java不采用)

标记清除法:就是分为标记和清除两个阶段进行处理内存中的对象,当然这种方式也有非常大的弊端,产生空间碎片问题,垃圾回收后造成内存空间不连续,不连续的内存空间的工作效率要低于连续的内存空间。(java不采用)

标记压缩法:标记压缩法在标记清除法基础之上做了优化,把存活的对象压缩到内存一端,而后进行垃圾清理。(java中老年代使用的就是标记压缩法)

分代算法(思想):就是根据对象的特点把内存分成N块,而后根据每个内存的特点使用不同的算法。对于新生代和老年代来说,新生代回收频率很高,但是每次回收耗时都很短,而老年代回收频率较低,但是耗时会相对较长,所以应该尽量减少老年代的GC.

分区算法(思想):其主要就是将整个内存分为N多个小的独立空间,每个小空间都可以独立使用,这样细粒度的控制一次回收都是在每个小空间中进行,而不对整个空间进行GC,从而提升性能,并减少GC的停顿时间。

3.GC停顿现象

        垃圾回收器的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以高效的执行,大部分情况下,会要求系统进入一个停顿的状态,停顿的目的是终止所有应用线程,只有这样系统才不会有新的垃圾产生,同时停顿保证了系统状态在某一个瞬间的一致性,也有益于更好的标记垃圾对象,因此在垃圾回收时,都会产生应用程序的停顿。

4.对象如何步入老年代

        一般而言对象首次创建会被放置在新生代的eden区,如果没有GC介入,则对象不会离开eden区,那么eden区的对象如何进入老年代?
        一般来讲,只要对象的年龄达到一定的大小,就会自动离开年轻代进入老年代,对象年龄是由对象经历数次GC决定的,在新生代每次GC之后如果对象没有被回收则年龄加1,虚拟机提供了一个参数来控制新生代对象的最大年龄,当超过这个年龄范围就会晋升老年代。

-XX:MaxTenuringThreshold 默认情况下为15,根据设置MaxTenuringThreshold参数,可以指定新生代对象经过多少次回收后进入老年代;另外,大对象(新生代eden区无法装入时,也会直接进入老年代)。JVM里有个参数可以设置对象的大小超过在指定的大小之后,直接晋升老年代。
-XX:PretenureSizeThreshold 使用PretenureSizeThreshold可以进行指定进入老年代的对象大小;

5.垃圾收集器种类

        Java虚拟机垃圾回收器不仅仅只有一种,什么情况下该使用哪种,对性能又有什么样的影响,这都是我们需要了解的。
• 串行垃圾回收器(生产环境性能不高的情况下应用,jdk早期都在用)

        串行回收器是指使用单线程进行垃圾回收的回收器。每次回收时,串行回收器只有一个工作线程,对于并行能力较弱的计算机来说,串行回收器的专注性和独占性往往有更好的性能表现。串行回收器可以在新生代和老年代使用,根据作用于不同的堆空间,分为新生代串行回收器和老年代串行回收器。
• -XX:+UseSerialGC 使用该参数设置使用新生代串行回收器和老年代串行回收器

• 并行垃圾回收器(对于目前互联网行业而言,硬件的计算能力都很强,基本都应用并行垃圾回收)

        并行回收器在串行回收器基础上做了改进,他可以使用多个线程同时进行垃圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的实际时间。
        ParNew回收器是一个工作在新生代的垃圾收集器,他只是简单的将串行回收器多线程化,他的回收策略和算法和串行回收器一样。
• -XX:+UseParNewGC:新生代ParNew回收器,老年代则使用串行回收器
• ParNew回收器工作时的线程数量可以使用:
• -XX:ParallelGCThreads:参数指定,一般最好和计算机的CPU相当,避免过多的线程影响性能。

        新生代 ParallelGC 回收器,使用了复制算法的收集器,也是多线程独占形式的收集器,但ParallelGC回收器有个非常重要的特点,就是它非常关注系统的吞吐量(即性能优先,生产环境中如果要优化系统吞吐量,就可以采用ParallelGC 回收器);提供了两个非常关键的参数控制系统的吞吐量:
• -XX:MaxGCPauseMillis(推荐采用默认):设置最大垃圾收集停顿时间,可用把虚拟机在GC停顿的时间控制在MaxGCPauseMillis范围内,如果希望减少GC停顿时间可以将MaxGCPauseMillis设置的很小,但是会导致GC频繁,从而增加了GC的总时间,降低了吞吐量。所以需要根据实际情况设置该值。
• -XX:GCTimeRatio(推荐采用默认):设置吞吐量大小,它是一个0到100之间的整数,默认情况下他的取值是99,那么系统将花费不超过1/(1+n)的时间用于垃圾回收,也就是1/(1+99) = 1%的时间。
        另外还可以指定 -XX:+UseAdaptiveSizePolicy(推荐使用) 打开自适应模式,在这种模式下,新生代的大小、eden、from/to的比例,以及晋升老年代的对象年龄参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。

        老年代 ParallelOldGC 回收器 也是一种多线程的回收器和新生代的ParallelGC 回收器一样,也是一种关注吞吐量的回收器,他使用了标记压缩算法进行实现。
• -XX:+UseParallelOldGC
• -XX:+ParallelGCThreads 可以设置垃圾收集时的线程数量

• CMS回收器(目前很多开源应用都在使用,原因是其可控性强,前提是内存足够的情况下应用)

        CMS全称为:Concurrent Mark Sweep 意为并发标记清除,他使用的是标记清除法主要关注系统停顿时间
• 使用 -XX:+UseConcMarkSweepGC 进行设置。
• 使用 -XX:ConcGCThreads 设置并发线程数量。
        CMS并不是独占的回收器,在CMS回收过程中,应用程序仍然在不停的工作,又会有新的垃圾不断产生,在使用CMS的过程中应该确保应用程序的内存足够可用(生产中应用CMS要将系统峰值调整到1.5倍,实际压测后得出的指标1.5倍最优,比如分配4G的内存就满足高峰期应用,那么就要增加到6G,防止CMS在运行时造成内存溢出)。CMS不会等到应用程序饱和的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置,-XX:CMSInitiatingOccupancyFraction来指定,默认为68,也就是说当老年代的空间使用率达到68%的时候,会执行CMS回收。如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行回收器进行垃圾回收(此为降级策略),这会导致应用程序中断,直到垃圾回收完成后才会正常工作,这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingOccupancyFraction的设置要根据实际的情况(推荐调整到50)。
• 在学习算法的时候说过,标记清除法有个缺点就是存在内存碎片的问题,那么CMS有个参数设置
• -XX:+UseCMSCompactAtFullCollecion 参数可以使CMS回收完成之后进行理;
• -XX:CMSFullGCsBeforeCompaction 参数可以设置进行多少次CMS回收之后,对内存进行一次压缩。

• G1回收器

        G1回收器(Garbage-First) 拥有独特的垃圾回收策略,G1属于分代垃圾回收器,区分新生代和老年代,依然有eden和from/to区,它并不要求整个eden区或者新生代、老年代的空间都连续,它使用了分区算法。
• 并行性:G1回收期间可多线程同时工作。
• 并发性:G1拥有与应用程序交替执行能力,部分工作可与应用程序同时执行,在整个GC期间不会完全阻塞应用程序。
• 空间整理:G1在分代GC:G1依然是一个分代的收集器,但是它是兼顾新生代和老年代一起工作,之前的垃圾收集器他们或者在新生代工作,或者在老年代工作,因此这是一个很大的不同。
• 回收过程中,不会像CMS那样在若干次GC后需要进行碎片整理,G1采用了有效复制对象的方式,减少空间碎片。
• 可预见性:由于分区的原因,G1可以只选取部分区域进行回收,缩小了回收的范围,提升了性能。
• 使用 -XX:+UseG1GC 应用G1收集器,
• 使用 -XX:MaxGCPauseMillis 指定最大停顿时间
• 使用 -XX:ParallelGCThreads 设置并行回收的线程数量

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值