java虚拟机之垃圾回收(二)

对象如何进入老年代

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

  • —XX:MaxTenuringThreshold,默认情况下为15:根据设置MaxTenuringThreshold参数,可以指定新生代对象需要经历多少次回收后进如老年代。
  • 另外,大对象(新生代eden区无法装入时,也会直接进入老年代)。JVM里有个参数可以设置对象的大小超过指定的大小之后,直接晋升老年代
  • -XX:PretenureSizeThreshold 可以指定进入老年代对象大小,但是要注意TLAB区域优先分配空间。
  • -XX:UserTLAB 虚拟机对于体积不大的对象会优先把数据分配到TLAB区域中,因此就失去了在老年代的分配。
TLAB

TLAB全称是Thread Local Allocation Buffer即线程本地分配缓存,从名字上看是一个线程专用的内存分配区域,是为了加速对象分配而生的。每一个线程都会产生一个TLAB,该线程独享的工作区域,java虚拟机使用这种TLAB区域来避免多线程冲突问题,提高了对象分配的效率。TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接分配到堆上。
参数设置:

  1. -XX:+UseTLAB 使用TLAB
  2. -XX:+TLABSize 设置TLAB大小
  3. -XX:+TLABRefillWasteFraction 设置维护进入TLAB空间的单个对象的大小,他是一个比例值,默认为64,即如果对象大于整个空间的1/64,则在堆创建对象。
  4. -XX:+PrintTLAB 查看TLAB信息
  5. -XX:+ResizeTLAB 自动调整TLABRefillWasteFraction阀值
对象创建流程图

对象创建流程

垃圾收集器
  1. 串行垃圾回收器:
    串行回收器是指用单线程进行垃圾回收的回收器。每次回收时,串行回收器只有一个工作线程,对于并行能力较弱的计算机来说,串行回收器的专注性和独占性往往有更好的性能表现。串行回收器可以在新生代和老年代使用,根据作用于不同的堆空间,分为新生代串行回收器和老年代串行回收器。
    使用-XX:+UseSerialGC 参数可以设置新生代串行回收器和老年代串行回收器
  2. 并行垃圾回收器(ParNew回收器):并行回收器在串行回收器的基础上做了改进,他可以使用多个线程同时进行垃圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需实际时间。
    ParNew回收器是一个工作在新生代的垃圾收集器,他只是简单的将串行回收器多线程化,他的回收策略和算法和串行回收器一样。
    使用-XX:+UseParNewGC 新生代ParNew回收器,老年代则使用串行回收器ParNew回收器工作时的线程数量可以使用-XX:ParallelGCThreads参数指定,一般最好和计算机的CPU相当,避免过多的线程影响性能
  3. 并行垃圾回收器(ParallelGC回收器):新生代ParallelGC回收器使用了复制算法的收集器,也是多线程独占形式的收集器,但ParallelGC回收器有个非常重要的特点,就是非常关注系统的吞吐量。
    提供了两个非常关键的差数控制系统的吞吐量。
    —XX:MaxGCPauseMillis:设置最大垃圾收集停顿时间,可以把虚拟机在GC停顿的时间控制在MaxGCPauseMillis范围内,如果希望减少GC停顿时间可以将MaxGCPauseMillis时间设置的很小,但是会导致GC频繁,从而增加了GC的总时间,降低了吞吐量。所以要根据实际情况设置该值。
    —XX:GCTimeRatio:设置吞吐量大小,它是一个0-100之间的整数,默认情况下他的取值是99,那么系统将花费不超过1/(n+1)的时间用于垃圾回收,也就是1/(1+99)的时间。另外还可以指定—XX:+UseAdaptiveSizePolicy打开自适应模式,在这种模式下,新生代的大小,、eden、from/to的比例,以及晋升老年代的对象年龄参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。
  4. 并行垃圾回收器(ParallelOldGC回收器):老年代ParallelOldGC回收器也是一种多线程的回收器,和新生代的ParallelGC回收器一样,也是一种关注吞吐量的回收器,它使用了标记压缩算法进行实现。
    —XX:+UseParallelOldGC进行设置
    —XX:+ParallelGCThreads也可以设置垃圾收集时的线程数量
  5. CMS回收器:Concurrent Mark Sweep 并发标记清除,它使用的是标记清除法,主要关注系统停顿时间。
    使用-XX:+UseConcMarkSweepGC进行设置
    使用-XX:ConcGCThreads设置并发线程数量
    CMS并不是独占的回收器,也就是说CMS回收的过程中,应用程序仍在不停的工作,又会有新的垃圾不断产生,所以在使用CMS的过程中应该确保应用程序的内存足够可用。CMS不会等到应用程序饱和的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定参数配置,用-XX:CMSInitiatingOccupancyFraction来指定,默认为68,也就是说当老年代的空间使用率达到68%的时候,会执行CMS回收。如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将会启动老年代串行回收器进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作,这个过程GC的停顿时间可能较长,所以,—XX:CMSInitiatingOccupancyFraction的设置要根据实际的情况。
  • 之前在学习垃圾回收算法时候说过垃圾回收算法,标记清除法的缺点是存在内存碎片的问题,那么CMS有个参数设置-XX:+UseCMSCompactAtFullCollection可以使CMS回收完成之后进行一次碎片整理,—XX:CMSFullGCsBeforeCompaction参数可以设置进行多少次CMS回收之后对内存进行一次压缩。
  1. G1回收器
    G1回收器(Garbage-First)是在jdk1.7中提出的垃圾回收器,从长期目标看是为了取代CMS回收器,G1回收器拥有独特的垃圾回收策略,G1属于分代垃圾回收器,区分新生代和老年代,依然有eden和from/to区,它不要求整个eden区、新生代、老年代的空间都连续,它使用了分区算法。
  • 并行性:G1回收期间可多线程同时工作
  • 并发性:G1拥有应用程序交替执行能力,部分工作可与应用程序同时执行,在整个GC期间不会完全阻塞应用程序。
  • 分代GC:G1依然是一个分代的收集器,但是它兼顾新生代和老年代一起工作。
  • 空间整理: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、付费专栏及课程。

余额充值