JVM机制理解与调优方案

作者:逍遥Sean
简介:一个主修Java的Web网站\游戏服务器后端开发者
主页:https://blog.csdn.net/Ureliable
觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言!

前言

很多Java开发岗位要求实际调优经验,难倒了JVM小白😭

想要掌握JVM调优首先理解JVM的组成和机制,明白GC的原理和算法,掌握调优工具,知道参数配置,随后在开发过程中根据项目需要进行配置或是机制优化💪
👇👇👇

另外,博主之前分享了一篇关于JVM的面试经验,欢迎友友学习评价~
文章链接: Java开发第二轮面试被疯狂问JVM相关,被整懵了!!赶紧好好复习一下

JVM机制理解与调优方案

  • 1 原理
    • 1.1 JVM内存分配
    • 1.2 JVM的主要组成部分及其作用?
    • 1.3 JVM运行时数据区包含哪些?
    • 1.4 JVM 对象创建步骤流程是什么?
  • 2 GC
    • 2.1 JVM垃圾回收机制,何时触发MinorGC等操作
    • 2.2 JVM的垃圾回收算法
  • 3 JVM调优
    • 3.1 JVM 调优的工具?
    • 3.2 常用的JVM调优参数?
    • 3.3 JVM调优方案总结

1 原理

1.1 JVM内存分配

Java虚拟机(JVM)内存分配主要分为以下几个步骤:

  1. 堆内存分配:Java中的对象都存储在堆内存中,当程序需要创建一个新对象时,JVM就会在堆中分配一块内存空间,并返回该对象的引用。

  2. 栈内存分配栈内存用于存放方法调用中的数据,如方法的参数、局部变量等。每当调用一个新方法时,JVM就会为该方法分配一块栈内存空间,并将该方法的参数和局部变量存储在该内存空间中。

  3. 方法区内存分配方法区用于存储类的元数据、静态变量、常量等数据,通常也称为“永久代”。当JVM需要加载一个类时,它就会在方法区中分配一块内存空间,并将该类的元数据等信息存储在该内存空间中。

  4. 本地内存分配本地内存用于存储使用JNI(Java Native Interface)调用的本地方法库的数据。当程序需要调用本地方法库时,JVM就会为该方法库分配一块本地内存空间,并将相关数据存储在该内存空间中。

在这里插入图片描述
在这里插入图片描述

1.2 JVM的主要组成部分及其作用?

  1. 类装载器(Class Loader):Java代码 -----> 字节码 的编译过程。JVM中的类装载器用于加载Java程序的类文件。它会将Java程序中的类文件加载到内存中,并生成对应的Java类。

  2. 运行时数据区(Runtime Data Area):把上一步编译得到的字节码加载到内存中。JVM中的运行时数据区用于存储Java程序中的数据。它包括方法区、堆、栈、程序计数器和本地方法栈。

  3. 执行引擎(Execution Engine):解析上一步加载而来的字节码,翻译成为系统指令,交由CPU执行。JVM中的执行引擎用于执行由字节码文件生成的指令。它是将Java程序转换为机器指令的重要组成部分。

  4. 本地库接口(Java Native Interface(JNI)):JVM中的JNI允许Java程序调用本地应用程序。JNI提供了一种标准的接口,使Java程序可以与C或C++程序进行交互。

  5. Java虚拟机语言规范(Java Virtual Machine Specification):诸如IO之类的由其他语言写成的本地库接口。JVM中的规范文件定义了Java编程语言的语法和语义。它描述了JVM如何解释Java程序,并将其转换为机器指令。

  6. 调试接口(Debugging Interface):JVM中的调试接口允许开发人员在代码执行期间调试Java程序。它提供了一些开发工具,如JMX(Java Management Extensions)和JVMPI(Java Virtual Machine Profiler Interface)。

1.3 JVM运行时数据区包含哪些?

程序计数器:行号指示器,通过改变该值,以选取下一步的指令
Java虚拟机栈:局部变量、方法出口等,为JVM服务
本地方法栈:局部变量、方法出口等,为本地Native方法服务
堆区:内存最大的一块,所有的对象实例都在这里分配内存
方法区:常量、静态变量等

1.4 JVM 对象创建步骤流程是什么?

  1. 类加载:JVM需要先加载类定义。如果定义这个类的.class文件还没有被加载,JVM就会把这个文件读进来,然后对它进行解析和验证。

  2. 分配内存:当类被加载后,JVM需要在堆上分配内存来存储对象。根据对象的类型和大小,JVM会在堆上分配一段连续的内存空间。

  3. 初始化成员变量:在对象创建的过程中,JVM需要初始化对象的所有成员变量。如果成员变量是基本类型,JVM会给其默认值;如果成员变量是引用类型,JVM会初始化为null。

  4. 执行构造函数:当内存空间分配完成并且成员变量初始化完成后,JVM会调用构造函数对对象进行初始化。

  5. 返回对象引用:构造函数执行完成后,对象就被创建成功了。JVM会返回对象的引用,开发者就可以通过该引用来访问和操作该对象。

2 GC

2.1 JVM垃圾回收机制,何时触发MinorGC等操作

分代垃圾回收机制:不同的对象生命周期不同。把不同生命周期的对象放在不同代上,不同代上采用最合适它的垃圾回收方式进行回收。
JVM中共划分为三个代:年轻代、年老代和持久代,

年轻代:存放所有新生成的对象;
年老代:在年轻代中经历了N次垃圾回收仍然存活的对象,将被放到年老代中,故都是一些生命周期较长的对象;
持久代:用于存放静态文件,如Java类、方法等。

新生代的垃圾收集器命名为“minor gc”,老生代的GC命名为”Full Gc 或者Major GC”.其中用System.gc()强制执行的是Full Gc.
判断对象是否需要回收的方法有两种:

  1. 引用计数。当某对象的引用数为0时,便可以进行垃圾收集。
  2. 对象引用遍历。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

触发GC(Garbage Collector)的条件:

  1. GC在优先级最低的线程中运行,一般在应用程序空闲即没有应用线程在运行时被调用。

  2. Java堆内存不足时,GC会被调用。

2.2 JVM的垃圾回收算法

简要记忆:

标记-清除:无用对象全部干掉
标记-整理:有用对象都向一边移动,边界以外的全部干掉
复制算法:左边内存快满时,将其中要保留的对象复制到右边内存中,然后整体干掉左边内存。右边同理,内存利用率仅有一半
分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

完整概念:

  1. 标记-清除算法(Mark-Sweep):首先标记所有活动对象,然后清除所有未标记的对象。
  2. 复制算法(Copying):将存活对象复制到一块新的内存中,然后清除旧的内存。
  3. 标记-整理算法(Mark-Compact):首先标记所有活动对象,然后将所有存活对象移到一端,最后清除端边界之外的所有对象。
  4. 分代收集算法(Generational):根据对象的生命周期划分为不同代,根据代的特点采用不同的垃圾回收算法,如新生代采用复制算法,老年代采用标记-整理算法。
  5. 并发标记-清除算法(Concurrent Mark-Sweep):在应用程序运行的同时标记和清除垃圾,减少停顿时间。
  6. G1算法(Garbage-First):将堆内存分成多个大小相等的区域,根据垃圾多少先清理垃圾最多的区域,提高垃圾回收效率。

3 JVM调优

3.1 JVM 调优的工具?

JVM 调优的常用工具包括以下几种:

  1. jstat:用于监视 JVM 运行状态和性能指标。
  2. jmap:用于生成 Java 堆转储快照并进行分析。
  3. jstack:用于生成 Java 线程转储快照并进行分析。
  4. VisualVM:是一个图形化的工具,可用于监视和分析 JVM 应用程序的运行状态和性能指标。
  5. jconsole:也是一个图形化的工具,可以监视和管理 JVM 应用程序。
  6. JVM Profiler:是一个高级的分析工具,可用于分析 JVM 应用程序的性能瓶颈。
  7. GCViewer:是一个用于分析 JVM 垃圾回收行为和性能的工具。

这些工具都有各自的特点和优劣,具体使用取决于实际调优需求。

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm这两款视图监控工具。
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
jvisualvm: JDK自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、 gc 变化等。

3.2 常用的JVM调优参数?

常用版:
• -Xms2048M最小内存2048M
• -Xmx2048M最大内存2048M
• -XX:NewRatio=4设置年轻的和老年代的内存比例为 1:4
• -XX:SurvivorRatio=8设置新生代 Eden 和 Survivor 比例为 8:2

• -XX:+UseConcMarkSweepGC指定使用 CMS + Serial Old 垃圾回收器组合;

• -XX:+PrintGC开启打印 gc 信息;

• -XX:+PrintGCDetails打印 gc 详细信息。

完整版:

  1. -Xms:设置JVM初始堆大小
  2. -Xmx:设置JVM最大堆大小
  3. -Xmn:设置年轻代大小
  4. -XX:SurvivorRatio:设置Eden区和Survivor区的比例
  5. -XX:MaxPermSize:设置永久代大小
  6. -XX:MaxTenuringThreshold:设置对象晋升年龄的最大值
  7. -XX:NewRatio:设置老年代与年轻代的比例
  8. -XX:+UseConcMarkSweepGC:使用CMS垃圾回收器
  9. -XX:+UseParallelGC:使用并行垃圾回收器
  10. -XX:ParallelGCThreads:设置并行垃圾回收线程数
  11. -XX:+CMSParallelRemarkEnabled:启用CMS回收完成后并行分析标记
  12. -XX:+UseParallelOldGC:使用并行老年代垃圾回收器
  13. -XX:MaxGCPauseMillis:设置最大垃圾回收停顿时间
  14. -XX:+AggressiveOpts:启用侵略性优化特性
  15. -XX:+OptimizeStringConcat:启用字符串拼接优化
  16. -XX:+UseBiasedLocking:启用偏向锁
  17. -XX:CompileThreshold:设置JIT编译阈值

3.3 JVM调优方案总结

  1. 调整内存分配参数:包括最大堆内存、最小堆内存、新生代大小等,以避免频繁的垃圾回收和内存溢出。

  2. 优化垃圾回收:可以通过选择不同的垃圾回收器,调整回收器选项等来实现。

  3. 选择合适的JVM版本:新版本的JVM可能会提供更好的性能和稳定性。

  4. 减少对象的创建:避免频繁的对象创建和销毁,尽量重用已经创建的对象。

  5. 使用线程池:尽量减少线程的创建和销毁,使用线程池来管理线程。

  6. 避免过度同步:使用适当的同步控制方式,避免过度使用锁和同步方法。

  7. 优化代码结构和算法:使用更高效的算法和数据结构,避免不必要的计算和内存消耗。

  8. 监控JVM运行状态:及时发现问题并解决,包括内存泄漏、线程死锁等。

  9. 使用JVM调试工具:如JVisualVM、JConsole和Java Flight Recorder等,以便更好地分析和解决问题。

注:以上方案须具体问题具体分析,不同应用场景可能需要不同的调优方法。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

2023年9月随笔之摩托车驾考

1. 回头看 日更坚持了273天。 读《SQL学习指南(第3版)》更新完成 读《高性能MySQL(第4版)》持续更新 学信息系统项目管理师第4版系列持续更新 9月码字81307字,日均码字数2710字,累计码字451704字&…

Node18.x基础使用总结(二)

Node18.x基础使用总结 1、Node.js模块化1.1、模块暴露数据1.2、引入模块 2、包管理工具2.1、npm2.2、npm的安装2.3、npm基本使用2.4、搜索包2.5、下载安装包2.6、生产环境与开发环境2.7、生产依赖与开发依赖2.8、全局安装2.9、修改windows执行策略2.10、安装包依赖2.11、安装指…

日期范围搜索

1.日期范围选择界面 <?xml version"1.0" encoding"utf-8"?> <ScrollViewandroid:layout_width"fill_parent"android:layout_height"fill_parent"xmlns:android"http://schemas.android.com/apk/res/android">…

桂院校园导航 静态项目 二次开发教程 1.2

Gitee代码仓库&#xff1a;桂院校园导航小程序 GitHub代码仓库&#xff1a;GLU-Campus-Guide 先 假装 大伙都成功安装了静态项目&#xff0c;并能在 微信开发者工具 和 手机 上正确运行。 接着就是 将项目 改成自己的学校。 代码里的注释我就不说明了&#xff0c;有提到 我…

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石①

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石① 第十九章 驱动程序基石①19.1 休眠与唤醒19.1.1 适用场景19.1.2 内核函数19.1.2.1 休眠函数19.1.2.2 唤醒函数 19.1.3 驱动框架19.1.4 编程19.1.4.1 驱动程序关键代码19.1.4.2 应用程序 19.1.5 上机实验19.1.6 使用环形缓…

89、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->Zset 相关命令

本次讲解要点&#xff1a; ** Set相关命令&#xff1a;是指value中的数据类型** 启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe …

【算法分析与设计】贪心算法(下)

目录 一、单源最短路径1.1 算法基本思想1.2 算法设计思想1.3 算法的正确性和计算复杂性1.4 归纳证明思路1.5 归纳步骤证明 二、最小生成树2.1 最小生成树性质2.1.1 生成树的性质2.1.2 生成树性质的应用 2.2 Prim算法2.2.1 正确性证明2.2.2 归纳基础2.2.3 归纳步骤2.3 Kruskal算…

【刷题笔记10.2】LeetCode: 罗马数字转整数

LeetCode: 罗马数字转整数 一、题目描述 二、分析 方法一&#xff1a; 将给定字符串s中的"IV", “IX”, “XL”, “XC”, “CD”, “CM” 全部替换为其他字符如&#xff1a;a, b, c, d, e, f 这种&#xff0c;然后就可以遍历累加了。 s s.replace("IV",…

python-切换镜像源和使用PyCharm进行第三方开源包安装

文章目录 前言python-切换镜像源和使用PyCharm进行第三方开源包安装1. 切换镜像源2. 使用PyCharm进行第三方开源包安装 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每…

7.3 调用函数

前言&#xff1a; 思维导图&#xff1a; 7.3.1 函数调用的形式 我的笔记&#xff1a; 函数调用的形式 在C语言中&#xff0c;调用函数是一种常见的操作&#xff0c;主要有以下几种调用方式&#xff1a; 1. 函数调用语句 此时&#xff0c;函数调用独立存在&#xff0c;作为…

ARINC825规范简介

ARINC825规范简介 机载CAN网络通用标准 ARINC825规范全称为机载CAN网络通用标准&#xff08;The General Standardization of CAN for Airborne Use&#xff09;。顾名思义&#xff0c;ARINC825规范是建立在CAN物理网络基础上的高层规范。CAN网络使用共享的双绞电缆传输数据&…

接雨水问题

接雨水问题 问题背景 LeetCode 42. 接雨水 接雨水问题是一个经典的计算雨水滞留量的问题&#xff0c;通常使用柱状图来表示不同高度的柱子。在下雨的情况下&#xff0c;柱子之间的凹陷部分能够存储雨水&#xff0c;问题的目标是计算这些柱子所能接收的雨水总量。 相关知识 …

【人工智能导论】线性回归模型

一、线性回归模型概述 线性回归是利用函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。简单来说&#xff0c;就是试图找到自变量与因变量之间的关系。 二、线性回归案例&#xff1a;房价预测 1、案例分析 问题&#xff1a;现在要预测140平方的房屋的价格&…

【HUAWEI】单臂路由

目录 ​ &#x1f96e;写在前面 &#x1f96e;2.1、拓扑图 &#x1f96e;2.2、操作思路 &#x1f96e;2.3、配置操作 &#x1f363;2.3.1、LSW4配置 &#x1f363;2.3.2、R2配置 &#x1f363;2.3.3、测试网络 &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &…

求∑(1,n)⌊k/i⌋∗i

对于[k/i]*i,我们可以分两端&#xff0c;前,最多有段&#xff0c;后边从到n&#xff0c;取值范围为1-&#xff0c;所以最多有段&#xff0c;共2*段。对于每段从i开始&#xff0c;其上界jk/(k/i)&#xff08;维持k/i不变最大范围i-j&#xff09;。 计算[k/i]*i时间复杂度降到级…

十大常见排序算法详解(附Java代码实现和代码解析)

文章目录 十大排序算法⛅前言&#x1f331;1、排序概述&#x1f334;2、排序的实现&#x1f335;2.1 插入排序&#x1f433;2.1.1 直接插入排序算法介绍算法实现 &#x1f433;2.1.2 希尔排序算法介绍算法实现 &#x1f335;2.2 选择排序&#x1f433;2.2.1 选择排序算法介绍算…

在linux下预览markdown的方法,转换成html和pdf

背景 markdown是一种便于编写和版本控制的格式&#xff0c;但却不便于预览——特别是包含表格等复杂内容时&#xff0c;单纯的语法高亮是远远不够的——这样就不能边预览边调整内容&#xff0c;需要找到一种预览方法。 思路 linux下有个工具&#xff0c;叫pandoc&#xff0c…

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过部署宝塔面板可视化管理华为云云耀云服务器

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之简单使用&#xff1a;通过部署宝塔面板可视化管理华为云云耀云服务器 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为…

【C语言经典100例题-66】(用指针解决)输入3个数a,b,c,按大小顺序输出。

代码&#xff1a; #include<stdio.h> #define _CRT_SECURE_NO_WARNINGS 1//VS编译器使用scanf函数时会报错&#xff0c;所以添加宏定义 swap(p1, p2) int* p1, * p2; {int p;p *p1;*p1 *p2;*p2 p; } int main() {int n1, n2, n3;int* pointer1, * pointer2, * point…

ARM---实现1-100求和任务

.text .globl _start_start:mov r0, #0x1mov r1, #0x1 给r1加一固定1不变mov r2, #0x64 100判断bl sumcmp r1, r2 sum:addcc r1, r1,#0x1 r1自增addcc r0, r0, r1 r0求和movcc pc,lrstop:b stop.end