我的编程空间,编程开发者的网络收藏夹
学习永远不晚

线上JVM是怎么优化的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

线上JVM是怎么优化的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

线上JVM是怎么优化的

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

jvm线程变化是怎样的

这篇文章主要介绍“jvm线程变化是怎样的”,在日常操作中,相信很多人在jvm线程变化是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jvm线程变化是怎样的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧
2023-06-03

JVM优化配置指导是怎么样的

JVM优化配置指导是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。本文向大家简单介绍一下JVM优化配置的概念,通常情况下是不建议在没有任何统计和分析的情况下去手动配置J
2023-06-17

JVM优化引起的逻辑错误怎么解决

这期内容当中小编将会给大家带来有关JVM优化引起的逻辑错误怎么解决,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。public class Test2 { public static void ma
2023-06-17

sql在线优化的方法是什么

SQL 在线优化的方法有以下几种:使用索引:确保表中的列上有合适的索引,以加快数据检索速度。优化查询语句:避免使用 SELECT *,只选择所需的列;避免使用子查询,尽量使用 JOIN 等操作;避免使用 OR 条件,尽量使用 IN 或者
sql在线优化的方法是什么
2024-04-09

Java虚拟机怎么利用JVM进行优化

本篇文章为大家展示了Java虚拟机怎么利用JVM进行优化,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言Java虚拟机是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最
2023-05-31

java jvm调优的方法是什么

Java虚拟机(JVM)调优是通过优化Java应用程序的运行时环境来提高性能和吞吐量的过程。以下是一些常见的JVM调优方法:1. 增加堆内存大小:通过增加JVM的堆内存大小,可以提高应用程序的性能。可以使用-Xmx和-Xms参数来指定最大和
2023-10-10

Java线程池优化的方法是什么

这篇文章主要介绍“Java线程池优化的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程池优化的方法是什么”文章能帮助大家解决问题。升级版线程池的优化1:新增了4种拒绝策略。分别为
2023-06-29

jvm内存调优的方法是什么

JVM内存调优的方法有以下几种:调整堆内存大小:可以通过设置-Xmx和-Xms参数来调整堆内存的大小。增大堆内存可以提高应用程序的性能,但也会增加垃圾回收的时间。调整垃圾回收器:JVM中的垃圾回收器可以根据不同的需求选择不同的算法和参数。通
2023-10-27

jvm性能调优的方法是什么

JVM性能调优的方法包括以下几个方面:1. 内存调优:通过调整JVM的堆内存大小(-Xmx和-Xms参数)来优化内存使用效率,避免过多的垃圾回收。同时,可以使用垃圾回收器的不同配置(如CMS、G1等)来适应不同的应用场景。2. 垃圾回收调优
2023-10-10

JVM 是怎么设计来保证new对象的线程安全

1、采用 CAS 分配重试的方式来保证更新操作的原子性 2、每个线程在 Java 堆中预先分配一小块内存,也就是本地线程分配缓冲(Thread Local AllocationBuffer,TLAB),要分配内存的线程,先在本地缓冲区中分配
2023-08-30

java在jvm上的执行流程是什么

Java在JVM上的执行流程如下:1. 编写Java源代码:首先,开发人员使用Java编程语言编写Java源代码。Java源代码是以.java文件的形式保存的。2. 编译Java源代码:使用Java编译器(javac),将Java源代码编译
2023-09-26

Java多线程怎么同步优化

这篇文章给大家分享的是有关Java多线程怎么同步优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。加入高速缓存带
2023-06-15

JVM调优的几种策略分别是什么

这期内容当中小编将会给大家带来有关JVM调优的几种策略分别是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。JVM参数调优是一个很头痛的问题,可能和应用有关系,别人说可以的对自己不一定管用。下面是本人一
2023-06-17

线上Linux服务器的优化经验有哪些

这期内容当中小编将会给大家带来有关线上Linux服务器的优化经验有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。什么是Linux服务器?Linux服务器就是采用Linux系统的网络服务器,同时也有采用
2023-06-05

SEO优化是怎么算费用的

本篇内容主要讲解“SEO优化是怎么算费用的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SEO优化是怎么算费用的”吧!1、关键词搜索结果数量你在百度搜索某个关键词时,比如在页面最下面有个“找到相
2023-06-10

在Fedora上怎么优化bash或zsh

这篇文章主要介绍“在Fedora上怎么优化bash或zsh”,在日常操作中,相信很多人在在Fedora上怎么优化bash或zsh问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在Fedora上怎么优化bash或
2023-06-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录