JVM GC算法以及调优

jvm的垃圾回收器是jvm的重要组成部分。GC负责着整个jvm运行时堆中对象的回收,保证jvm的性能。由于Java执行GC垃圾回收时会阻塞其他所有的线程,这样是对用户极不友好的,即对GC的优化重点是降低阻塞的时间,对GC的调优也就是对jvm的性能调优的重点。

jvm堆的内存模式(画的比较简陋,忘海涵)
这里写图片描述

jvm为堆内存划分了几块区域如上图:
最左边的new generation是新生代,新生代分为3块区域一个是eden区,还有两个suvivor区。最右边的是老年代区域。

实例化一个对象时
1. 绝大多数刚刚被创建的对象会存放在eden空间。
2. 在eden空间执行了第一次GC之后,存活的对象被移动到其中一个survivor空间。
3 .此后,在eden空间执行GC之后,存活的对象会被堆积在同一个survivor空间。
4. 当一个survivor空间饱和,还在存活的对象会被移动到另一个survivor空间。之后会清空已经饱和的那个survivor空间。
5. 在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。

从上面执行过程可以看出survivor区域必定有一块是空的,用JVM监控工具可以观察两个survivor区域的状况,如果两个survivor区域都有对象,则说明此时jvm是有问题的。

GC常用算法:

  1. 串行收集器(Serial GC)
    最古老的垃圾回收算法没有之一,是以前运行在单核cpu的服务器下 的。新生代、老年代都使用串行算法回收。
    算法的第一步是标记老年代中依然存活对象。第二步是从头开始检查堆内存空间,并且只留下依然幸存的对象。最后一步,从头开始,顺序地填满堆内存空间,并且将对内存空间分成两部分:一个保存着对象,另一个空着。

    在jvm下配置的参数是 -XX:+UseSerialGC

  2. 并行垃圾回收器(Parallel GC)
    parallel GC可以看成是Serial GC的升级版,它是采用多线程的机制是执行GC操作,所以执行GC过程阻塞时间较短。新生代采用的是并行算法,而老年代依然采用的是串行算法。

    在jvm下配置的参数是 -XX:+UseParallelGC,是jvm默认的GC回收算法。这里写图片描述

  3. 并发标记扫描垃圾回收器(CMS收集器)
    Concurrent Mark Sweep是应用程序线程和GC线程交替执行
    使用的标记-清除算法,并发阶段会降低吞吐量。它经常被用在那些对于响应时间要求十分苛刻的应用之上。
    老年代收集器。

    在jvm下配置的参数是 -XX:+UseConcMarkSweepGC

  4. G1收集器
    G1垃圾回收器适用于堆内存很大的情况,他将堆内存分割成不同的区域,并且并发的对其进行垃圾回收。G1也可以在回收内存之后对剩余的堆内存空间进行压缩。并发扫描标记垃圾回收器在STW情况下压缩内存。G1垃圾回收会优先选择第一块垃圾最多的区域.

    在jvm下配置的参数是 -XX:+UseG1GC

根据应用场景的不同选择不同的GC算法是必要的。还有一些重要的参数,例如分配给堆的内存大小最大是多少 -Xmx参数,初始化是多少-Xms,一般我们将-Xmx与-Xms设置相同,避免jvm频繁的变更堆内存的大小消耗cpu的性能;还有新生代的区域大小参数的配置-XX:NewRatio:3,一般配置的是2-3,这时新生代的内存大小=Xmx/NewRatio+1。

一般推荐的JVM参数
这里写图片描述

猜你喜欢

转载自blog.csdn.net/CSDNzhangtao5/article/details/67017737