说到jvm调优,实质上就是对java内存的合理使用,进而减少full gc的频率和时间,提高应用的运行效率。下面就从内存结构,内存分配与回收和垃圾收集器这三个方面来进行说明。

1:jvm的内存结构

jvm内存结构

方法区和堆是线程共享的。java栈,本地方法栈和程序计数器是每个线程私有的。调优的主要对象就是方法区和堆栈。

1)方法区 :所有定义的方法的信息都保存在该区域,静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在方法区中。(java8里彻底被移除,取而代之的是元数据区)

2)堆简单来说就是虚拟机启动时创建,用于存放对象实例的地方,几乎所有的对象(包含常量池)都在堆上分配内存。

堆结构

年轻代(Young Generation):分为伊甸区(Eden space)和幸存者区(Survivor pace)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。若幸存 0区也满了,再对该区进行垃圾回收,然后移动到1区。然后来回15次(可以设置)后,就会进入老年代。当然,如果幸存区不够大的情况,会直接进入年老代。

老年代(Old Generation):新生区经过多次GC仍然存活的对象移动到老年区。若老年区也满了,那么这个时候将产生MajorGC(FullGC),进行老年区的内存清理。若老年区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。

2:JVM内存分配与回收

新生代GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。

老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC经常会伴随至少一次的Minor GC(并非绝对),Major GC的速度一般会比Minor GC的慢10倍以上。

实际运用过程中,可以通过-XX:+PrintGCDetails 来打印垃圾回收的整个过程。

虚拟机判断是否可以垃圾回收的算法是可达性算法,大概的意思就是从Gc roots(类加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量等等)根节点对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

判断一个类是否可以回收的三个标准:

1)该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。

2)加载该类的 ClassLoader 已经被回收。

3)该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法

虚拟机可以对满足上述3个条件的无用类进行回收,这里说的仅仅是“可以”,而并不是和对象一样不使用了就会必然被回收。

3:垃圾回收器

常用的垃圾回收器主要有,

1)Serial(串行)收集器(-XX:+UseSerialGC)

这个模式对占有内存较少的应用很管用,用在新生代,可以和CMS配合使用。

2)ParNew(并发)收集器 (-XX:+UseParallelGC)

是多线程版的串行收集器。用在新生代,可以和CMS配合使用。

2)CMS收集器(-XX:+UseConcMarkSweepGC)

CMS收集器也被称为短暂停顿并发收集器。它是对年老代进行垃圾收集的。CMS收集器通过多线程并发进行垃圾回收,尽量减少垃圾收集造成的停顿。因为垃圾回收的方法不同,所以比并发收集器的停顿时间更短,但是会和cpu抢占资源,还会产生大量碎片。

4)G1收集器(-XX:+UseG1GC)

G1收集器和其他的收集器运行方式不一样,不区分年轻代和年老代空间。主要针对配备多颗处理器及大容量内存的机器. G1将Java堆划分为多个大小相等的独立区域(Region),虽保留新生代和老年代的概念,但不再是物理隔阂了,它们都是(可以不连续)Region的集合。

分配大对象(直接进Humongous区,专门存放短期巨型对象,不用直接进老年代,避免Full GC的大量开销)不会因为无法找到连续空间而提前触发下一次GC。

lG1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内完成垃圾收集。

垃圾回收器没有最好的,各有特点,要根据自己的业务场景选择合适的垃圾回收器。以下是给出的几点建议;

1. 如果内存小于100M,使用串行收集器

2. 如果是单核,并且没有停顿时间的要求,串行或JVM自己选择

3. 如果允许停顿时间超过1秒,选择并行或者JVM自己选

4.如果响应时间最重要,并且不能超过1秒,使用并发收集器,CMS和G1.

最后从实战的角度,谈一些经验,供大家参考

第一步:确定调优的两个指标:停顿时间(垃圾收集器做垃圾回收中断应用执行的时间)和吞吐量(花在垃圾回收的时间和应用时间的占比)。吞吐量一般在90%以上就可以了。

第二步:打印GC日志(-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log)

第三步:分析GC原因,调整jvm参数。主要的几个参数就是,堆栈参数,垃圾收集器以及对应垃圾收集器的各个参数。(在没懂各个参数的含义之前建议不要在生产上调整)。可视化分析工具有gceasy,GCViewer.

附录:GC常用参数

堆栈设置

-Xss:每个线程的栈大小

-Xms:初始堆大小,默认物理内存的1/64

-Xmx:最大堆大小,默认物理内存的1/4

-Xmn:新生代大小

-XX:NewSize:设置新生代初始大小

-XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。

-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。

-XX:MetaspaceSize:设置元空间大小

-XX:MaxMetaspaceSize:设置元空间最大允许大小,默认不受限制,JVM Metaspace会进行动态扩展。

垃圾回收统计信息

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename

收集器设置

-XX:+UseSerialGC:设置串行收集器

-XX:+UseParallelGC:设置并行收集器

-XX:+UseParallelOldGC:年轻代和老年代都使用并行回收收集器

-XX:+UseParNewGC:在新生代使用并行收集器

-XX:+UseParalledlOldGC:设置并行老年代收集器

-XX:+UseConcMarkSweepGC:设置CMS并发收集器

-XX:+UseG1GC:设置G1收集器

-XX:ParallelGCThreads:设置用于垃圾回收的线程数

并行收集器设置

-XX:ParallelGCThreads:设置并行收集器收集时使用的CPU数。并行收集线程数。

-XX:MaxGCPauseMillis:设置并行收集最大暂停时间

-XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

CMS收集器设置

-XX:+UseConcMarkSweepGC:设置CMS并发收集器

-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。

-XX:ParallelGCThreads:设置并发收集器新生代收集方式为并行收集时,使用的CPU数。并行收集线程数。

-XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩

-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收

-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收

-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况

-XX:ParallelCMSThreads:设定CMS的线程数量

-XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发

-XX:+
UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理

G1收集器设置

-XX:+UseG1GC:使用G1收集器

-XX:ParallelGCThreads:指定GC工作的线程数量

-XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区

-XX:GCTimeRatio:吞吐量大小,0-100的整数(默认9),值为n则系统将花费不超过1/(1+n)的时间用于垃圾收集

-XX:MaxGCPauseMillis:目标暂停时间(默认200ms)

-XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%)

-XX:G1MaxNewSizePercent:新生代内存最大空间

-XX:TargetSurvivorRatio:Survivor填充容量(默认50%)

-XX:MaxTenuringThreshold:最大任期阈值(默认15)

-XX:InitiatingHeapOccupancyPercen:老年代占用空间超过整堆比IHOP阈值(默认45%),超过则执行混合收集

-XX:G1HeapWastePercent:堆废物百分比(默认5%)

-XX:G1MixedGCCountTarget:参数混合周期的最大总次数(默认8)                                                        希望对你有所帮助!

架构师的成长必经之路相关推荐

  1. Netstars CTO陈斌:架构师的成长之路

    中生代技术 链接技术大咖,分享技术干货 接力技术,链接价值 架构与架构师 Architect,即架构一词可以溯源到希腊语ἀρχιτέκτων , 指的是建筑的规划,设计和建造过程和结果.现在也用于指系 ...

  2. [架构之路-4]:架构师 - 架构师的四大架构价值等级与架构师全面成长之路

    目录 第1章 架构师的四大架构价值等级 第一等级L1: 一知半解型(入门架构师)-- 辅助价值 第二等级L2: 拆解还原型(初级架构师)-- 表层价值.协调价值 第三等级L3: 革新型(中级架构师)- ...

  3. 阿里P7架构师的成长之路

    前言 系统架构师是近几年来在国内外迅速成长并发展良好的一个职位,它的重要性及给互联网行业所带来的影响是不言而喻的.很多程序员把成为一名优秀的架构师作为自己职业生涯奋斗的目标,但很多人努力却用不对地方, ...

  4. 架构 php_十年PHP架构师的成长之路,程序员必备

    不知不觉自己做开发已经十年了,这十年中我获得了技术能力.CTO.大公司的经历.但再仔细一想,这十年中我至少浪费了五年时间走了很多弯路,这五年可以足够让自己成长为一个优秀的程序员,我用这五年时间和很多程 ...

  5. 二本毕业生逆袭成大厂架构师的成长心得

    大家好,我叫金泽,架构师一枚. 我的成长轨迹跟大多数人一样,平凡而曲折.二本大学毕业的我,机缘巧合之下报名了某Java 培训,结束后便直接进入东软,开启了人生第一份工作,一待就是 3 年.后来,怀揣着 ...

  6. 分享Android资深架构师的成长之路,建议收藏

    背景 经常有网友在知乎问答提两个问题:"现在学习移动开发还有前景吗?""开发还有什么可以研究的?".网友回复:"现在还学移动开发?如同49年加入国军! ...

  7. 安卓开发指南!分享Android资深架构师的成长之路,面试心得体会

    前言 最近有不少人问我这样一个问题:「我刚接触编程,准备学习下Android开发,但是担心现在市场饱和了,Android开发的前景怎么样?」 想着可能有很多人都有这样的担心,于是就赶紧写篇文章,来跟你 ...

  8. 一个十年Java架构师的成长之路分享

    前言 我搞JAVA也有些日子了, 因为我比较贪玩,上进心不那么强, 总是逼不得已为了高薪跳槽才去学习, 所以也没混成什么大牛, 但好在现在也已经成家立业, 小日子过的还算滋润, 起码顶得住一月近万元的 ...

  9. 【云计算】阿里云云计算架构师ACE成长路线v2

    1.缘起ACA 好几个月前看到了架构师就想考,一直没机会. 暑假放假后,本来想从ACA学起的,结果意外的机会开始乱搞,一星期就拿到了ACP的证书. ACE架构师似乎就没那么简单了,可能要很多精力把,目 ...

最新文章

  1. Android 之 Fagment 完全解析
  2. springMVC,mybatis配置事务
  3. dmx计算机,DMX是什么意思
  4. spring四种依赖注入方式
  5. python中dict函数_dict()函数以及Python中的示例
  6. 写给mybatis小白的入门指南
  7. 昔日光伏巨头赛维LDK迎“接盘侠” 平煤系深度整合产业链
  8. 燃气管理 php,智能燃气管理信息系统设计
  9. 波特率和比特率的关系
  10. uniApp实现h5页面唤醒app
  11. 离散数据:析取范式与合取范式
  12. v-if报undefined
  13. vim基本指令(一)
  14. 读 Timothy Gowers 之 Mathematics: A Very Short Introduction
  15. 物联网-位置信息、定位技术与位置服务
  16. Mac使用Homebrew极速安装启动RabbitMQ一把梭
  17. 猿学~黑客、红客、白帽子之间的技术较量,为什么大公司都有黑客团队?
  18. matlab的simulink中的normal模式acclerator等模式的选择方法
  19. 鸿蒙系统安装苹果电脑,好消息!华为鸿蒙OS系统,解决了苹果、安卓系统的一大难题...
  20. 如何做好基层管理者(二)

热门文章

  1. 上海女孩,你凭什么和我谈车子房子
  2. 用ISO-8859-1解决Python 'utf-8' codec can't decode bytes in position 924-925问题
  3. IOS网络第二天 - 05-黑酷-NSXMLparser解析(略)
  4. 需求说明定义一个超市会员类属性名字会员号余额积分打印名字 会员号 余额和积分充值的方法余额 要累加 输出一下余额消费的方法余额减 积分累加 每消费10元
  5. vc2010设置为静态编译
  6. 【MADRL】MADDPG运行MPE
  7. 如何下载无偏移的谷歌电子/卫星地图
  8. RIM微软效仿苹果 将提供免费MobileMe同类服务
  9. Android 基于Kotlin Flow实现一个倒计时功能
  10. LeetCode JAVA语言全部解题思路+答案代码+多种解法+关键注释(持续更新...)