java性能优化之分代回收

目录
  • 前言
  • 什么是分代回收?
  • 为什么采用分代回收?
    • 年轻代回收
    • 老年代回收
    • 更加厉害的回收方式
  • 垃圾收集器的权衡

前言

我们今天一起来聊一聊关于垃圾收集的细节问题。垃圾收集是通过何种方式减少stop the world?这将是垃圾回收的重点内容。

什么是分代回收?

什么是分代回收,初次接触的同学肯定是很懵的。还记得我们前面在介绍使用jvisualvm工具的时候,从它给我们反馈的视图上看到,有几个不同的数据块,且是动态的,如下图红圈的部分:

从左到右分别是:

  • Metaspace :元空间
  • Old :老年代
  • Eden + S0 + S1 : 这三个加在一起称为年轻代

到目前为止,市面上常见的垃圾收集器,都是按照这种分代回收的方式进行垃圾回收的,但是其内部的实现方式却有很大的差别。

本章我们的重点是 老年代 和 年轻代 。

通过上图我们发现,年轻代有三部分组成:

  • Eden :通常称为Eden区,翻译过来也可以称为伊甸园区。
  • S0 和 S1:通常称为survivor区,翻译过来称为幸存者区,由幸存者0和幸存者1所组成。

为什么采用分代回收?

绝大部分的对象,它们的生命周期非常短暂,甚至绝大多数都是临时对象,垃圾收集器的设计需要适应这种情况。

我们都知道对象创建,存放在堆中,而不论是老年代还是年轻代都是堆中的一部分。

年轻代回收

当对象被创建后,会被分配至年轻代,随着对象的增加,年轻代会被占满,此时将会停止全部的应用线程,并进行垃圾回收,没有被使用的对象会被回收,仍然被使用的对象将会被移动到其他的地方。这种操作就是MinorGC,年轻代回收。

使用分代算法的最根本原因,是为了尽量的减少垃圾回收造成的停顿,我们可以从下面两个方面考虑:

  • 新生代是堆的一部分,仅处理一部分空间,一定比整个堆空间的时间要短,停顿时间也就短。但是我们一定会想到,停顿的频率增加了。
  • 年轻代的空间分配方式,对性能有影响。年轻代中,eden占据大部分空间,而S0和S1平分剩余空间。对象首次创建会在Eden中,经过一次垃圾回收时,Eden被清空,未使用的对象被回收,仍然使用的对象进入Survior或老年代。Eden区的清空操作,相当于进行了一次压缩整理

即使是年轻代的回收,仍然存在时空停顿

老年代回收

前面提到,除了在Eden可能将对象移动到老年代当中,对于在Survior当中没有被回收的对象,最终也会移动到老年代当中。当老年代被占满时,会停止所有的应用线程,找到不再使用的对象进行垃圾回收。这个过程将会停顿很长时间,我们称之为Full GC

更加厉害的回收方式

前面的描述其实都是较为简单的垃圾收集器,在停止应用线程后去发现不再使用的对象,进行回收。

然而实际上,通过一些定制,和复杂的计算,我们可以在应用线程运行时去找到不再使用的对象。在前一篇文章一笔带过的CMS和G1收集器,就是如此。他们不需要停止应用线程就可以找到不再使用的对象,所以它们也叫做concurrent垃圾收集器

垃圾在查找的时候将会占用很多时间,当然查找算法将是下一章节我们需要学习的内容。然而concurrent垃圾收集器可以尽可能的减少应用的停顿时间,它们也可以称为低停顿收集器

这种垃圾收集器缩减应用的停顿时间,其代价是占用更多的CPU。即使是G1和CMS也会遇到长时间的Full GC,这将是我们需要针对实际环境调优的方向。

垃圾收集器的权衡

前面简单描述了不同垃圾收集器的垃圾收集方式,以及造成的影响。但是在我们选择垃圾收集器的过程中还是需要一定的权衡,才能使其发挥最佳的性能。

我们需要考虑的重点就是:

  • 吞吐量:如果你的系统需要大批量的处理数据等,换句话说,不要求每次响应时间最快,而平均响应时间更加重要,Parallel收集器也许会有不错的表现。
  • 响应时间:简单来说,如果你想要你的接口获得更快的响应时间,那么concurrent收集器将是更好的选择。
  • CPU性能:使用current收集器势必要消耗更多的CPU资源。

到此这篇关于java性能优化之分代回收的文章就介绍到这了,更多相关java性能优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java程序员编程性能优化必备的34个小技巧(总结)

    1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 控制资源的使用,通过线程同步来控制资源的并发访问: 控制实例的产生,以达到节约资源的目的: 控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信. 2.尽量避免随意使用静态变量 要知道,当某个对象被定义为static变量所引用,那么GC通常是不会回收这个对象所占有的内存,如: 此时静态变量b的生命周期与A类同步,如

  • JAVA下单接口优化实战TPS性能提高10倍

    概述 最近公司的下单接口有些慢,老板担心无法支撑双11,想让我优化一把,但是前提是不允许大改,因为下单接口太复杂了,如果改动太大,怕有风险.另外开发成本和测试成本也非常大.对于这种有挑战性的任务,我向来是非常喜欢的,因为在解决问题的过程中,可以学习到很多东西. 当时我只是知道下单接口慢,但是没人告诉我慢在哪里,也即是说,哪些瓶颈导致下单接口慢了.其实没人知道也没关系的,因为我们可以通过压测来找到具体的瓶颈. 下面会详细介绍一下,在本次压测中遇到的问题以及如何解决,期间用了什么工具. 用到的工具和

  • Java for循环性能优化实现解析

    这篇文章主要介绍了Java for循环性能优化实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 完成同样的功能,用不同的代码来实现,性能上可能会有比较大的差别,所以对于一些性能敏感的模块来说,对代码进行一定的优化还是很有必要的.今天就来说一下java代码优化的事情,今天主要聊一下对于for(while等同理)循环的优化,它作为三大结构之一的循环,在我们编写代码的时候会经常用到.循环结构让我们操作数组.集合和其他一些有规律的事物变得更加的方

  • Java并发编程如何降低锁粒度并实现性能优化

    在高负载多线程应用中性能是非常重要的.为了达到更好的性能,开发者必须意识到并发的重要性.当我们需要使用并发时, 常常有一个资源必须被两个或多个线程共享. 在这种情况下,就存在一个竞争条件,也就是其中一个线程可以得到锁(锁与特定资源绑定),其他想要得到锁的线程会被阻塞.这个同步机制的实现是有代价的,为了向你提供一个好用的同步模型,JVM和操作系统都要消耗资源.有三个最重要的因素使并发的实现会消耗大量资源,它们是: 上下文切换 内存同步 阻塞 为了写出针对同步的优化代码,你必须认识到这三个因素以及如

  • 一次 Java 服务性能优化实例详解

    背景 前段时间我们的服务遇到了性能瓶颈,由于前期需求太急没有注意这方面的优化,到了要还技术债的时候就非常痛苦了. 在很低的 QPS 压力下服务器 load 就能达到 10-20,CPU 使用率 60% 以上,而且在每次流量峰值时接口都会大量报错,虽然使用了服务熔断框架 Hystrix,但熔断后服务却迟迟不能恢复.每次变更上线更是提心吊胆,担心会成为压死骆驼的最后一根稻草,导致服务雪崩. 在需求终于缓下来后,leader 给我们定下目标,限我们在两周内把服务性能问题彻底解决.近两周的排查和梳理中,

  • java性能优化之编译器版本与平台对应关系

    目录 JIT编译器版本 默认情况JVM如何选择编译器? 如何判断当前环境jvm使用的编译器? 小节 本章节更加具体化的学习编译器还有哪些可以优化的方便,让你的应用展现出更好的性能. JIT编译器版本 JIT编译器有不同的版本,而最终你使用哪种,取决于你所使用的系统平台.前面的文章我们说到编译器有-client和-server,具体划分应该是如下所示: -client 32位client编译器 -server 32位server编译器 -d64 64位server编译器 如果你的系统是32位,那么

  • Java List的remove()方法陷阱以及性能优化

    Java List在进行remove()方法是通常容易踩坑,主要有一下几点 循环时:问题在于,删除某个元素后,因为删除元素后,后面的元素都往前移动了一位,而你的索引+1,所以实际访问的元素相对于删除的元素中间间隔了一位. 几种常见方法 1.使用for循环不进行额外处理时(错误) //错误的方法 for(int i=0;i<list.size();i++) { if(list.get(i)%2==0) { list.remove(i); } } 2.使用foreach循环(错误) for(Inte

  • java性能优化之分代回收

    目录 前言 什么是分代回收? 为什么采用分代回收? 年轻代回收 老年代回收 更加厉害的回收方式 垃圾收集器的权衡 前言 我们今天一起来聊一聊关于垃圾收集的细节问题.垃圾收集是通过何种方式减少stop the world?这将是垃圾回收的重点内容. 什么是分代回收? 什么是分代回收,初次接触的同学肯定是很懵的.还记得我们前面在介绍使用jvisualvm工具的时候,从它给我们反馈的视图上看到,有几个不同的数据块,且是动态的,如下图红圈的部分: 从左到右分别是: Metaspace :元空间 Old

  • java性能优化四种常见垃圾收集器汇总

    目录 前言 常见的垃圾回收器和算法 serial 串行垃圾收集器 Parallel 多线程垃圾收集器 CMS 收集器 G1 收集器 显式垃圾收集 前言 本篇文章我们来具体看看如何选择合适的垃圾收集器.每种垃圾收集器都有其不同的算法实现和步骤,下面我们简单描述下我们常见的四种垃圾收集器的算法过程,感兴趣的同学们最好先看下以下的两篇文章去增加理解.分别介绍了一些垃圾回收的基本概念,和各种垃圾回收器回收的过程,内容重复,本章不会在去单独讲解一遍.所以本章做一些归纳总结. JVM GC 垃圾收集梳理总结

  • Java性能优化技巧汇总

    本文实例汇总了Java性能优化技巧.分享给大家供大家参考.具体分析如下: 这里参考了些书籍,网络资源整理出来,适合于大多数Java应用 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1.尽量使用final修饰符. 带有final修饰符的类是不可派生的.在JAVA核心API中,有许多应用final的例子,例如java.lang.String.为String类指定final防止了使用者覆盖length()方法.另外,如

  • Java性能优化之数据结构实例代码

    -举例(学生排课)- 正常思路的处理方法和优化过后的处理方法: 比如说给学生排课.学生和课程是一个多对多的关系. 按照正常的逻辑 应该有一个关联表来维护 两者之间的关系. 现在,添加一个约束条件用于校验.如:张三上学期学过的课程,在排课的时候不应该再排这种课程. 所以需要出现一个约束表(即:历史成绩表). 即:学生选课表,需要学生成绩表作为约束. -方案一:正常处理方式- 当一个学生进行再次选课的时候.需要查询学生选课表看是否已经存在. 即有如下校验: //查询 学生code和课程code分别为

  • java性能优化之代码缓存优化

    目录 JIT编译器版本 默认情况JVM如何选择编译器? 如何判断当前环境jvm使用的编译器? 代码缓存 代码缓存占满发生在什么情况? 代码缓存默认大小 如何确定正好的代码缓存? 如何监控代码缓存? JIT编译器版本 JIT编译器有不同的版本,而最终你使用哪种,取决于你所使用的系统平台.前面的文章我们说到编译器有-client和-server, 具体划分应该是如下所示: -client 32位client编译器 -server 32位server编译器 -d64 64位server编译器 如果你的

  • 10种简单的Java性能优化

    最近"全网域(Web Scale)"一词被炒得火热,人们也正在通过扩展他们的应用程序架构来使他们的系统变得更加"全网域".但是究竟什么是全网域?或者说如何确保全网域? 扩展的不同方面 全网域被炒作的最多的是扩展负载(Scaling load),比如支持单个用户访问的系统也可以支持10 个.100个.甚至100万个用户访问.在理想情况下,我们的系统应该保持尽可能的"无状态化(stateless)".即使必须存在状态,也可以在网络的不同处理终端上转化

  • JavaScript垃圾回收机制(引用计数,标记清除,性能优化)

    目录 一.前言 二.何为垃圾 三.垃圾回收 四.可达性(Reachability) 五.可达性举例 层次关联 相互关联 可达孤岛 六.垃圾回收算法 引用计数 标记清除 七.性能优化 分代回收 增量收集 空闲收集 八.总结 一.前言 垃圾回收是JavaScript的隐藏机制,我们通常无需为垃圾回收劳心费力,只需要专注功能的开发就好了.但是这并不意味着我们在编写JavaScript的时候就可以高枕无忧了,伴随着我们实现的功能越来越复杂,代码量越积越大,性能问题就变的越来越突出.如何写出执行速度更快,

  • java性能调优System的gc垃圾回收方法

    目录 一.什么是System.gc()? 二.谁可以调用System.gc()? 三.调用System.gc()有什么弊端? 四.哪些场景适合显式调用System.gc()? 五.如何检测您的应用程序正在进行System.gc()? 六.如何禁止GC显式调用或调整调用GC的频率? 搜索和替换 通过JVM参数强制禁止 RMI 一.什么是System.gc()? System.gc()是用Java,C#和许多其他流行的高级编程语言提供的API.当它被调用时,它将尽最大努力从内存中清除垃圾(即未被引用

  • java性能分析jconsole详解

    目录 jconsole简介 jconsole远程 前言: 本章节继续学习java性能优化的相关知识.重点学习什么是jconsole,以及如何使用?它能帮助我们做什么? jconsole简介 提供JVM图形化视图,包括内存.线程.类.cpu等信息.用户可以通过jconsole工具去连接指定的jvm,监控jvm的变化. 我们可以在jdk的安装文件bin当中找到它: 双击运行会打开如下界面,上面是本地的java进程,下面是通过远程的方式连接服务器上面的java进程. 我们随便点击一个本地进程得到如下的

随机推荐