JVM实战(13)——JVM优化概述

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析

阶段4、深入jdk其余源码解析

阶段5、深入jvm源码解析

一、简介

本章,我们先来对系统运行过程中可能会遇到的各种JVM性能问题作个概述,以此为引子,作为后续实战篇的铺垫。

JVM性能优化其实就是针对JVM内存分配、参数设置进行优化,目的是减少GC次数,避免对象频繁进入老年代。所以,我们来先来回顾下新生代和老年代的垃圾回收过程,并看下可能会引发的各种JVM性能问题。

在正式开始之前,我先给出一份JVM调优模板,这份模板基本上涵盖了JVM调优所需的所有核心参数,后续我们所有的调优也会围绕它展开:
-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 -XX:UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:CMSParallellInitialMarkEnabled -XX:CMSScavengeBeforeRemark -XX:DisableExplicitGC -XX:PrintGCDetail -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath:/usr/local/app/oom.hprof

上述有些参数看不懂没关系,我们在后续的各个实战章节中都会陆续提到,这里先简要说下:
首先,JVM中各块内存区域大小的分配是根据系统运行模型来配置的,然后是ParNew和CMS这两种垃圾回收器的配置,特别注意CMS的一些参数,主要是提升CMS的效率和性能,还有就是打印GC日志,日志可以借助后续章节会讲到的jstat工具进行分析,最后两个参数是在发生内存溢出异常时,自动dump出内存快照,然后就可以通过MAT等工具进行分析了。

二、JVM性能问题

JVM运行时,最核心的区域就是Java堆内存,这里会存放我们系统创建出来的各种对象。而且堆内存通常划分为新生代和老年代,新生代存放新创建出来的各种对象。所以,我们先来看下新生代GC会有哪些问题。

2.1 新生代GC

随着系统的不断运行,新生代中的对象会越来越多,直到快被塞满。此时会根据GC Roots去寻找存活的对象。GC Roots一般是类静态变量或方法的局部变量。由于我们创建对象最多的地方是在方法内,方法运行完毕,局部变量就没有了,所以新生代中这种对象其实占了99%,这也是新生代对象存活率低的原因。

新生代进行Minor GC时,会采用 复制算法 ,将Eden区和一块Survivor区的存活对象复制到另一块Survivor区,然后清空Eden和之前的Survivor。同时,新生代GC期间会”Stop the World“,即只允许GC线程进行回收工作,其它工作线程都会被挂起。

假设一次新生代的GC需要20ms,那么此时对于用户发送的请求,这20ms内是无法处理的,系统会卡顿20ms。但是新生代的GC速度非常快,所以只要不频繁GC,其实对系统是没什么影响的。所以,新生代GC其实没什么好调优的,只要多分配点堆内存,保证Survivor区空间充足,那么低峰时期一般几小时才有一次新生代GC,高峰期也最多几分钟一次新生代GC。

那么,什么时候新生代GC会对系统产生很大的影响呢?

当系统部署在大内存机器上时,比如32核64G的机器,新生代的Eden区可能有32G以上的内存。

此时,如果系统的负载特别高(比如部署了Kafka、Elasticsearch每秒处理上万的请求),那么可能导致Eden区的几十G空间在短短几分钟内被塞满。而此时进行新生代GC会停止系统的运行,由于新生代空间非常大,GC时间会很长,可能长达数秒钟。

对于一个高负载高并发的系统,每隔几分钟就停顿几秒去进行新生代GC,是不可接受的。

解决方案一般就是使用G1垃圾回收器,因为G1可以设置一个预期停顿时间(比如20ms),那么G1基于它的Region内存划分原理,就可以在运行一段时间之后,回收一部分Region,控制时间在20ms内,然后再运行再回收。

所以, G1天生就适合在这种大内存的机器上运行,可以完美解决大内存垃圾回收时间过长的问题。

2.2 老年代GC

之前给大家讲过新生代中对象晋升到老年代的几个可能条件:

  • 年龄太大
  • 符合动态年龄判断规则
  • 大对象
  • 新生代GC后存活的对象放不下Survivor区

上述条件中,关键是动态年龄判断和对象放不下Survivor区,从而导致大量对象频繁进入老年代:

老年代GC非常耗时,无论是CMS还是G1。通常老年代GC要比新生代GC慢十倍以上,所以针对老年代GC的优化还是要先从新生代GC入手,合理分配内存和设置JVM参数,尽量让对象不要频繁进入老年代。

三、各种GC分类

在基础篇,我们介绍过各种GC类型,Minor GC、Full GC、Mixed GC、Young GC等等。本节我们就来统一梳理下。

3.1 Minor GC/Young GC

当新生代的Eden区域被占满后,实际就需要触发新生代的GC,这就是所谓的”Minor GC“,也可以称之为”Young GC“。后续章节,我们统一用Young GC指代新生代的GC。

触发时机: 新生代的Eden区域被占满后。

3.2 Full GC/Old GC

Old GC是仅仅针对老年代区域进行垃圾回收。而Full GC则是针对新生代、老年代、永久代的全体内存空间进行垃圾回收。后续章节,我们统一用Old GC指代老生代的GC。

触发时机: 老年代空间不够。具体时机可细分为以下几种:

  1. 进行Young GC之前:如果老年代的连续可用内存空间 < 新生代历次晋升的平均大小,此时先触发一次Old GC清理老年代,然后再执行Young GC。
  2. 进行Young GC之后:如果存活对象要进入老年代,但是老年代的连续可用内存空间 < 存放对象的大小,此时必须触发一次Old GC。
  3. 老年代的内存使用率超过了92%,此时也会触发Old GC。

在很多JVM的实现机制里,当上述几种条件达到时,实际触发的其实是Full GC,这个Full GC会包含Young GC、Old GC和永久代GC。

3.3 Mixed GC

Mixed GC是G1垃圾回收器中特有的概念,在G1中,一旦老年代占据了Java堆内存的45%,就会触发Mixed GC,此时对新生代和老年代都进行垃圾回收。

触发时机: G1特有,老年代空间占据到Java堆内存的45%。

3.4 永久代GC

永久代一般存放着类信息、常量池等等。在进行Full GC的时候,会顺带对永久代进行GC,一般来说永久代里的东西是不需要回收的,如果永久代真的满了,回收之后也没腾出足够的空间来,就会抛出OOM异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/319776.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日一题——LeetCode1128.等价多米诺骨牌对的数量

先尝试暴力解法&#xff1a; var numEquivDominoPairs function(dominoes) {var count0for(let i0;i<dominoes.length-1;i){for(let ji1;j<dominoes.length;j){if((dominoes[i][0]dominoes[j][0] && dominoes[i][1]dominoes[j][1]) || (dominoes[i][0]dominoes…

Qt/QML编程学习之心得:小键盘keyboard(36)

小键盘对于qml应用是经常用到的,在qml里面,就如一个fileDialog也要自己画一样,小键盘keyboard也是要自己画的,对于相应的每个按键的clicked都要一一实现的。 这里有一个示例: 代码如下: import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Window 2.0 im…

Redis面试篇

redis面试题主要内容 面试官在面试时主要会问以下这些方面的问题 下面是一些问题示例&#xff1a; redis-使用场景 缓存 缓存穿透 介绍 缓存穿透&#xff1a;查询一个不存在的数据&#xff0c;mysql查询不到数据也不会直接写入缓存&#xff0c;就会导致每次请求都会去查数…

2.1 常用计算机网络体系结构

2.1 常用计算机网络体系结构 2.1.1 OSI体系结构 1、为了使不同体系结构的计算机网络都能够互联&#xff0c;国际标准化组织于1977年成立了专门机构研究该问题&#xff0c;不久他们就提出了一个试图使各种计算机在世界范围内都能够互连成网的标准框架&#xff0c;也就是著名的…

Redis命令 - Lists命令组常用命令

先创建一个 key 叫做 mylist&#xff0c;mylist存一个list。 list数据类型底层是一个链表。先进后出&#xff0c;后进先出。 命令中的L&#xff08;Left&#xff09;、R&#xff08;Right&#xff09;代表链表的头部L&#xff08;下标0的位置&#xff09;和尾部R&#xff08;…

mysql5.7之从入门到放弃

系列文章目录 第一章 MySQL5.7之从入门到放弃 第二章 MySQL从入门到放弃之数据库体系结构与管理 第三章 MySQL基础应用之DDL、DCL、DML、DQL 文章目录 系列文章目录前言一、Mysql的介绍和安装&#xff1f;1、什么是数据&#xff1f;2、什么是数据库管理系统&#xff08;DBMS&a…

基于深度学习的老照片修复系统

技术栈 深度学习 pytorch tensorflow python 卷积神经 神经网络 照片修复 vue 老照片修复 扫描褪色 残损照片或胶片 调整暗调/高光以改善面效果 修正曝光斑痕 背景&#xff1a; 随着时间的流逝&#xff0c;许多老照片可能会褪色、损坏或曝光不当。这些老照片记录了宝贵的回忆…

如何在Windows 11的桌面中添加此电脑图标,这里提供四种方法

将“此电脑”图标添加到Windows 11桌面,使文件更容易访问。虽然Window的11酷设计从一开始就没有包含这个图标,但没必要担心。取回它很容易。你可以通过“设置”菜单、快捷方式或使用“控制面板”再次返回。有几种方法可以恢复此图标。 在这篇文章中,我们将探讨不同的方法,…

Windows下使用clion调试LevelDB与rocksdb

目录 关于leveldb下载leveldb源码增加测试文件更新cmake文件运行 关于RocksDB下载RocksDB代码修改CMakelist.txt运行 参考资料&#xff1a; 关于leveldb 下载leveldb源码 链接: leveldbGit地址 增加测试文件 使用clion打开项目&#xff0c;在根目录下新建一个app目录&#…

超详细的嵌入式cJSON使用注意事项,持续补充中......

文章目录 一、堆内存不足1.1 问题描述1.2 解决办法 二、内存泄露2.1 忘记Delete2.2 忘记Free2.3 串口数据接收缺少部分字符导致的内存泄露(自己的问题)问题分析 2.4 内存泄露在Cortex-M3内核会发生什么&#xff1f; cJSON开源库地址&#xff1a; cJSON 一、堆内存不足 1.1 问…

第十二讲 单片机驱动彩色液晶屏 如何打包bin档

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

Python-- if...else

在 Python 中&#xff0c;if 语句是用来进行条件判断的基本结构。它允许您根据一个或多个条件的真假来执行不同的代码块。Python 的 if 语句的基本语法如下&#xff1a; if condition:# do something elif another_condition:# do something else else:# do something if none…

【Linux】线程池实现

&#x1f4d7;线程池实现&#xff08;单例模式&#xff09; 1️⃣线程池概念2️⃣线程池代码样例3️⃣部分问题与细节&#x1f538;类成员函数参数列表中隐含的this指针&#x1f538;单例模式&#x1f538;一个失误导致的bug 4️⃣调用线程池完成任务 1️⃣线程池概念 线程池是…

C#,求最长回文字符串的马拉车(Manacher)算法的源代码

一、回文字符串&#xff08;Palindromic String&#xff09; 回文字符串&#xff08;Palindromic String&#xff09;是指前、后向读起来完全相同的字符串。 回文字符串除了答题似乎没有什么用处 :P 二、求解思路 求解字符串的回文子串的基本思路&#xff1a; 1、遍历每个位…

C# 图解教程 第5版 —— 第25章 反射和特性

文章目录 25.1 元数据和反射25.2 Type 类25.3 获取 Type 对象25.4 什么是特性25.5 应用特性25.6 预定义的保留特性25.6.1 Obsolete 特性25.6.2 Conditional 特性25.6.3 调用者信息特性25.6.4 DebuggerStepThrough 特性25.6.5 其他预定义特性 25.7 关于应用特性的更多内容25.7.1…

springboot怎样设置全局的traceId(包括MQ)

一、Controller打印TraceId 1、拦截所有的controller&#xff0c;输入输出将traceId放入MDC中&#xff1a; package com.perkins.ebicycle.mobile.trace;import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors;import…

深思熟虑可能性模型介绍与使用

深思熟虑可能性模型介绍与使用 如何联系我 作者&#xff1a;鲁伟林 邮箱&#xff1a;thinking_fioa163.com或vlinyes163.com 版权声明&#xff1a;文章和记录为个人所有&#xff0c;如果转载或个人学习&#xff0c;需注明出处&#xff0c;不得用于商业盈利行为。 背景 20…

操作系统详解(5.1)——信号(Signal)的相关题目

系列文章&#xff1a; 操作系统详解(1)——操作系统的作用 操作系统详解(2)——异常处理(Exception) 操作系统详解(3)——进程、并发和并行 操作系统详解(4)——进程控制(fork, waitpid, sleep, execve) 操作系统详解(5)——信号(Signal) 文章目录 题目第一问第二问第三问 题目…

ES搜索的安装以及常用的增删改查操作(已经写好json文件,可以直接使用)

1.es的下载 https://www.elastic.co/cn/downloads/past-releases 2.elasticsearch安装及配置&#xff0c;遇到9200访问不了以及中文乱码&#xff0c;能访问了却要账户密码等问题 Elasticsearch启动后访问9200失败_http://localhost:9200无返回值-CSDN博客 3.开启es服务&#x…

Qat++,轻量级开源C++ Web框架

目录 一.简介 二.编译Oat 1.环境 2.编译/安装 三.试用 1.创建一个 CMake 项目 2.自定义客户端请求响应 3.将请求Router到服务器 4.用浏览器验证 一.简介 Oat是一个面向C的现代Web框架 官网地址&#xff1a;https://oatpp.io github地址&#xff1a;https://github.co…