返回顶部
首页 > 资讯 > 精选 >线上JVM是怎么优化的
  • 235
分享到

线上JVM是怎么优化的

2023-06-04 23:06:33 235人浏览 独家记忆
摘要

本篇内容介绍了“线上JVM是怎么优化的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JVM的内存模型是什么样子的?JVM内存模型可以大致可划

本篇内容介绍了“线上JVM是怎么优化的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

JVM的内存模型是什么样子的?

JVM内存模型可以大致可划分为线程私有区域和共享区域,线程私有区域由虚拟机栈、本地方法栈、程序计数器组成,而共享区域由堆、元数据空间(方法区)组成。

再有人问你JVM的内存模型就回想下上面的图,但是知道JVM的内存模型的样子还是不行的,还要知道他们分别干什么的。

虚拟机栈/本地方法栈

当你碰到过StackOverflowException这个异常的时候,有没有思考下为什么会出现这样的异常呢?答案就在虚拟机栈中,JVM会为每个方法生成栈帧然后将栈帧压入虚拟机栈中。

举个粟子:假设JVM参数-Xss设置为1m,如果某个方法里面创建一个128kb的数组,那这个方法在同一个线程中只能递归4次,再递归第五次的时候就会报StackOverflowException异常,因为虚拟机栈的大小只有1m,每次递归都需要为方法在虚拟机栈中分配128kb的空间,很显示到第五次的时候就空间不足了。

程序计数器

程序计数器是一个记录着当前线程所执行的字节码的行号指示器。JVM的多线程是通过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。也就是说,某个线程在执行过程中可能会因为时间片耗尽而被挂起,而另一个线程获取到时间片开始执行。

简单的说程序计数器的主要功能就是记录着当前线程所执行的字节码的行号指示器。

方法区(元数据区)

方法区存储了类的元数据信息、静态变量、常量等数据。

堆(heap)

平常大家使用new关键字创建的对象都会进入堆中,堆也是GC重点照顾的区域,堆会被划分为:新生代、老年代,而新生代还会被进一步划分为Eden区和Survivor区:

新生代中的Eden区和Survivor区,是根据JVM回收算法来的,只是现在大部分都是使用的分代回收算法,所以在介绍堆的时候会直接将新生代归纳为Eden区和Survivor区。

小结

JVM内存模型小结:

  • JVM内存模型划分为线程私有区域和共享区域

  • 虚拟机栈/本地方法栈负责存放线程执行方法栈帧

  • 程序计数器用于记录线程执行指令的位置

  • 方法区(元数据区)存储类的元数据信息、静态变量、常量等数据

  • 堆(heap)使用new关键字创建的对象都会进入堆中,堆被划分为新生代和老年代

什么时候对象可以被收回?

JVM判断对象回收有两种方式:引用记数、GC Roots,引用记数比较简单,JVM为每个对象维护一个引用计数,假设A对象引用计数为零说明没有任务对象引用A对象,那A对象就可以被回收了,但是引用计数有个缺点就是无法解决循环引用的问题。

GC Roots通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明对象是不可用的。

在Java中,可以作为GC Roots的对象包括下面几种:

  • 虚拟机栈中引用的对象;

  • 方法区中类静态属性引用的对象;

  • 方法区中的常量引用的对象;

  • 本地方法栈中JNI(即一般说的Native方法)的引用的对象;

小结

总的来说就是当一个对象通过GC Roots搜索不到时,说明对象可以被回收了,但什么时候回收还要看GC的心情!

常见的垃圾回收器算法有哪些,各有什么优劣?

标记清除

这种算法分两分:标记、清除两个阶段,
标记阶段是从根集合(GC Root)开始扫描,每到达一个对象就会标记该对象为存活状态,清除阶段在扫描完成之后将没有标记的对象给清除掉。

这个算法有个缺陷就是会产生内存碎片,如上图B被清除掉后会留下一块内存区域,如果后面需要分配大的对象就会导致没有连续的内存可供使用。

标记整理

标记整理就没有内存碎片的问题了,也是从根集合(GC Root)开始扫描进行标记然后清除无用的对象,清除完成后它会整理内存。

这样内存就是连续的了,但是产生的另外一个问题是:每次都得移动对象,因此成本很高。

复制算法

复制算法会将JVM推分成二等分,如果堆设置的是1g,那使用复制算法的时候堆就会有被划分为两块区域各512m。给对象分配内存的时候总是使用其中的一块来分配,分配满了以后,GC就会进行标记,然后将存活的对象移动到另外一块空白的区域,然后清除掉所有没有存活的对象,这样重复的处理,始终就会有一块空白的区域没有被合理的利用到。

两块区域交替使用,最大问题就是会导致空间的浪费,现在堆内存的使用率只有50%。

小结

JVM回收算法小结:

  • 标记清除速度快,但是会产生内存碎片;

  • 标记整理解决了标记清除内存碎片的问题,但是每次都得移动对象,因此成本很高;

  • 复制算法没有内存碎片也不需要移动对象,但是导致空间的浪费;

什么时候对象会进入老年代?

新创建出来的对象一开始都会停留在新生代中,但随着JVM的运行,有些存活的长的对象会慢慢的移动到老年代中。

根据对象年龄

JVM会给对象增加一个年龄(age)的计数器,对象每“熬过”一次GC,年龄就要+1,待对象到达设置的阈值(默认为15岁)就会被移移动到老年代,可通过-XX:MaxTenuringThreshold调整这个阈值。

一次Minor GC后,对象年龄就会+1,达到阈值的对象就移动到老年代,其他存活下来的对象会继续保留在新生代中。

动态年龄判断

根据对象年龄有另外一个策略也会让对象进入老年代,不用等待15次GC之后进入老年代,他的大致规则就是,假如当前放对象的Survivor,一批对象的总大小大于这块Survivor内存的50%,那么大于这批对象年龄的对象,就可以直接进入老年代了。

假如Survivor 2是100m,如果A + B + D的内存大小超过50m,现在D的年龄是10,那E都会被移动到老年代。实际上这个计算逻辑是这样的:年龄1 + 年龄2 + 年龄n的多个对象总和超过Survivor区的50%,那就会把年龄n以上的对象都放入老年代。

大对象直接进入老年代

如果设置了-XX:PretenureSizeThreshold这个参数,那么如果你要创建的对象大于这个参数的值,比如分配一个超大的字节数组,此时就直接把这个大对象放入到老年代,不会经过新生代。

这么做就可以避免大对象在新生代,屡次躲过GC,还得把他们来复制来复制去的,最后才进入老年代,这么大的对象来回复制,是很耗费时间的。

什么是空间分配担保策略?

JVM在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,如果大于,则此次Minor GC是安全的如果小于,则虚拟机会查看HandlePromotionFailure设置项的值是否允许担保失败。如果HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小,如果大于则尝试进行一次Minor GC,但这次Minor GC依然是有风险的;如果小于或者HandlePromotionFailure=false,则改为进行一次Full GC。

如何优化减少Full GC?

将前面的一些问题总结下来,然后应用到线上,那JVM应该如何优化减少Full GC呢?以标准的4核8G机器为例说明,首先系统预留4G,其他4G按如下规则分配 :

  • 堆内存:3g

  • 新生代:1.5g

  • 新生代Eden区:1228m

  • 新生代Survivor区:153m

  • 方法区:256m

  • 虚拟机栈:1m/thread

设置参数如下:

-Xms3072m-Xmx3072m-Xmn1536m-Xss=1m-XX:PermSize=256m-XX:MaxPermSize=256m-XX:HandlePromotionFailure-XX:SurvivorRatio=8
估算系统每秒占用内存数量

在优化JVM之前,要先估算要系统每秒占用的内存数量,如有个日活百万的商场系统,每日下单量在20w左右,按照一天8个小时算,那订单服务的每秒大概会有500个请求,然后粗略的估算下每个请求占用多少内存,计算出每秒要花费多少内存。

假设是每秒500个请求,每个请求需要分配100k的空间,那1秒需要分配大约50m的内存。

计算下多长时间触发一次Minor GC

按照之前的估算1秒需要分配大约50m的内存的话,Eden区的空间是1228m那平均每25秒就要执行一次Minor GC。

检查下Survivor区是否足够

按照上面的模型,每25秒就要执行一次Minor GC,GC执行期间并不能回收掉所有的新生代中的对象,那每秒50m那每次GC执行期间还会剩下大约100m无法回收的对象会进入Survivor区,但是别忘记JVM有动态年龄判断机制,这样设置下来Survivor的空间明显小了一点,所以将新生代设置2048m,才能避免触发动态年龄判断:

-Xms3072m-Xmx3072m-Xmn2048m...
大对象直接进入老年代

大对象一般是长期存活和使用的对象,一般来说设置1M的对象直接进入老年代,这样避免大对象一直处于新生代中来回复制,所以加上PretenureSizeThreshold=1m参数。

...-XX:PretenureSizeThreshold=1m...
合理设置对象年龄阈值

Minor GC后默认躲过15次垃圾回收后自动升入老年代,按照我们的评估25秒触发一次Minor GC,如果按照MaxTenuringThreshold参数的默认值,躲过15次GC后,应该是6分钟之后的事了,结合当前业务场景这里可以降低一点,让那些本应该进入老年代的对象,尽快的进入老年代,避免复制成本和浪费新生代空间,从而导致新生代Survivor空间不足,引发Full GC。

...-XX:MaxTenuringThreshold=6...

“线上JVM是怎么优化的”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 线上JVM是怎么优化的

本文链接: https://lsjlt.com/news/240304.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 线上JVM是怎么优化的
    本篇内容介绍了“线上JVM是怎么优化的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JVM的内存模型是什么样子的?JVM内存模型可以大致可划...
    99+
    2023-06-04
  • jvm线程变化是怎样的
    这篇文章主要介绍“jvm线程变化是怎样的”,在日常操作中,相信很多人在jvm线程变化是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jvm线程变化是怎样的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-03
  • JVM优化配置指导是怎么样的
    JVM优化配置指导是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。本文向大家简单介绍一下JVM优化配置的概念,通常情况下是不建议在没有任何统计和分析的情况下去手动配置J...
    99+
    2023-06-17
  • 如何优化Kubernetes上的JVM Warm-up
    这篇文章主要讲解了“如何优化Kubernetes上的JVM Warm-up”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何优化Kubernetes上的JV...
    99+
    2024-04-02
  • JVM优化引起的逻辑错误怎么解决
    这期内容当中小编将会给大家带来有关JVM优化引起的逻辑错误怎么解决,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。public class Test2 {  ...
    99+
    2023-06-17
  • sql在线优化的方法是什么
    SQL 在线优化的方法有以下几种: 使用索引:确保表中的列上有合适的索引,以加快数据检索速度。 优化查询语句:避免使用 SELEC...
    99+
    2024-04-09
    sql
  • Java虚拟机怎么利用JVM进行优化
    本篇文章为大家展示了Java虚拟机怎么利用JVM进行优化,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言Java虚拟机是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最...
    99+
    2023-05-31
    java jvm ava
  • java jvm调优的方法是什么
    Java虚拟机(JVM)调优是通过优化Java应用程序的运行时环境来提高性能和吞吐量的过程。以下是一些常见的JVM调优方法:1. 增...
    99+
    2023-10-10
    java jvm
  • Linux上怎么优化MySQL
    本篇内容主要讲解“Linux上怎么优化MySQL”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux上怎么优化MySQL”吧!一、CPU首先从CPU说起。你...
    99+
    2024-04-02
  • Java线程池优化的方法是什么
    这篇文章主要介绍“Java线程池优化的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程池优化的方法是什么”文章能帮助大家解决问题。升级版线程池的优化新增了4种拒绝策略。分别为:M...
    99+
    2023-06-29
  • jvm性能调优的方法是什么
    JVM性能调优的方法包括以下几个方面:1. 内存调优:通过调整JVM的堆内存大小(-Xmx和-Xms参数)来优化内存使用效率,避免过...
    99+
    2023-10-10
    jvm
  • jvm内存调优的方法是什么
    JVM内存调优的方法有以下几种: 调整堆内存大小:可以通过设置-Xmx和-Xms参数来调整堆内存的大小。增大堆内存可以提高应用程...
    99+
    2023-10-27
    jvm
  • 线上千万级大表排序优化
      大家好我是不一样的科技宅,每天进步一点点,体验不一样的生活,今天我们聊一聊Mysql大表查询优化,前段时间应急群有客服反馈,会员管理功能无法按到店时间、到店次数、消费金额 进行排序。经过排查发现是Sql执行效率低,并且索引效率低下。 应...
    99+
    2020-07-18
    线上千万级大表排序优化
  • 怎么去解析JVM调优
    怎么去解析JVM调优,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。你对JVM调优的概念是否了解,这里和大家分享一下,首先看一下JVM调优工具,主要有Jconso...
    99+
    2023-06-17
  • java在jvm上的执行流程是什么
    Java在JVM上的执行流程如下:1. 编写Java源代码:首先,开发人员使用Java编程语言编写Java源代码。Java源代码是以...
    99+
    2023-09-26
    java jvm
  • Java多线程怎么同步优化
    这篇文章给大家分享的是有关Java多线程怎么同步优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。加入高速缓存带...
    99+
    2023-06-15
  • 线上Linux服务器的优化经验有哪些
    这期内容当中小编将会给大家带来有关线上Linux服务器的优化经验有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。什么是Linux服务器?Linux服务器就是采用Linux系统的网络服务器,同时也有采用...
    99+
    2023-06-05
  • JVM 是怎么设计来保证new对象的线程安全
    1、采用 CAS 分配重试的方式来保证更新操作的原子性 2、每个线程在 Java 堆中预先分配一小块内存,也就是本地线程分配缓冲(Thread Local AllocationBuffer,TLAB),要分配内存的线程,先在本地缓冲区中分配...
    99+
    2023-08-30
    jvm
  • JVM调优的几种策略分别是什么
    这期内容当中小编将会给大家带来有关JVM调优的几种策略分别是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。JVM参数调优是一个很头痛的问题,可能和应用有关系,别人说可以的对自己不一定管用。下面是本人一...
    99+
    2023-06-17
  • jvm GC调优工具怎么用
    这篇文章主要介绍“jvm GC调优工具怎么用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“jvm GC调优工具怎么用”文章能帮助大家解决问题。JVM 在程序执行的过程中, 提供了GC行为的原生数据。...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作