所谓STW现象(Stop-The-World)是指在执行垃圾收集算法时,Java应用程序的其他所有线程(除了垃圾收集线程之外的线程)都被挂起.此时,系统只允许GC线程继续运行,其他线程全部暂停,等待GC线程执行完毕后才能继续执行.这些工作都是由虚拟机在后台自动发起和自动完成的,是在用户不可见的情况下把用户正常工作的线程全部停掉,举个例子,某个接口平时可能只需要50ms的RT,忽然某次调用花费了200ms.因此STW对实时性要求很高的系统来说是难以接受的.
垃圾回收器的种类 既然有STW现象,那么有没有解决方案呢?这就是我们接下来要讲的,垃圾回收器的种类,目前为止,JVM一共为我们提供了七种垃圾回收器,其中年轻代有三种,老年代有三种,另外还有一种特殊的G1:
当然,在更新版本的JDK中还有一种ZGC,为未来垃圾回收器提供了一种趋势,有兴趣的童鞋可以自行了解.
性能调优的目的和具体过程有了前面的铺垫,终于来到了我们最重要的正题:如何进行JVM性能调优?在我看来JVM调优的具体步骤分为如下几步:
确定调优的目的,选择合适的GC collector
调整JVM heap的大小
调整young generation在整个JVM heap中所占的比重.
确定调优的目的,选择合适的GC collector由于每种垃圾回收器的特性并不相同,因此我们需要根据我们的调优目的选择合适的垃圾回收器,比如,我们需要降低STW的停顿时间,那我们就不能选用串行和并行的垃圾回收器,而应该选用并发的垃圾回收器,即CMS,与之搭配的新生代垃圾回收器就应该选用ParNew.目前一般主流互联网公司都是用CMS垃圾回收器.
调整JVM heap的大小 确定了垃圾回收器的类型,就需要调整JVM heap的大小,在这一步的时候,首先我们需要了解JVM相关的一些指令,比如可以在启动java程序时加上
-XX:+HeapDumpOnOutOfMemoryError,当发生OOM时,JVM会自动为我们生成DUMP文件
-XX:+PrintGCDetails -Xloggc:D:\gclogger\gc.log -XX:+PrintGCDateStamps 生成GC日志
-Xms2g -Xmx2g 当然,还应该要根据实际情况设置heap的最大最小值,童鞋们要知道,默认情况下,java程序启动的最小heap大小为1/64物理内存,最大值为1/4物理内存,一般要求我们最大最小值保持一致,避免JVM频繁扩容和缩容导致不必要的性能浪费.
确定了heap的大小,还需要确定新生代的比重
–Xmn1500m -XX:MetaspaceSize=150M
当然,再厉害的架构师也不可能一次就调整得出最佳的JVM配置参数,而是应该多设置几组不同的值,放到生产环境(或者和生产环境一样的环境,比如阿里内部有预发环境,和生产环境保持一致)进行性能测试,通过对比结果得出最佳的JVM性能调优参数,完成JVM性能调优.
总结读完了本篇文章,我相信童鞋们应该或多或少会有些收获.掌握JVM调整的核心步骤:
确定调优的目的,选择合适的GC collector
调整JVM heap的大小
调整young generation在整个JVM heap中所占的比重.
不了解如何进行JVM的调优的人,把本文内容好好理解后,能让面试官刮目相看;了解JVM调优,但是条理不清晰的童鞋,可能会对JVM调优有更清晰的认识.总而言之,笔者认为本文是一篇满满的干货,网上许多讲JVM调优的博文,并没有这么系统的讲解过真正应该如何进行JVM调优.当然笔者能力有限,如文章有错误,欢迎指正,毕竟是人就会犯错.
PS:一入JVM深似海,从此再也出不来.对JVM有兴趣的童鞋,可以钻研,但是在经验不足之前,不建议太过深入了解JVM,否则会耽误自己.当然,立志要成为一名牛逼的架构师,这些都是必须要会的.
本文我们讲完了JVM,下一篇开始,让我们继续学习JAVA锁相关的内容.
如果觉得博主写的不错,欢迎关注博主微信公众号,博主会不定期分享技术干货!