【高级篇】Java JVM实战 之 内存调优

news2024/9/21 5:48:08

文章目录

  • 一、通过Jprofiler调式Dump文件错误
    • ⛅ 什么是Jprofiler?
    • ⚡使用Jprofiler调试Dump文件
  • 二、堆内存调优
  • 三、 GC垃圾回收器
  • 四、GC常用算法
    • ❄️引用计数法
    • ⛄复制算法
    • ♨️标记清除算法
    • ⛽标记压缩
    • ⚠️标记清除压缩
  • 五、JMM
  • ⛵小结

一、通过Jprofiler调式Dump文件错误

⛅ 什么是Jprofiler?

JProfiler 是一个 用于分析运行JVM内部情况的专业工具。 在开发中你可以使用它,用于质量保证,也可以解决你的生产系统遇到的问题

JProfiler处理四个主要问题

方法调用

这通常被称为"CPU分析"。方法调用可以通过不同的方式进行测量和可视化, 分析方法调用可以帮助了解你的应用程序正在做什么,并找到提高其性能的方法。

分配

分析堆上对象的分配、引用链和垃圾回收属于"内存分析"的范畴。 这个功能可以让你解决内存泄漏,总之使用更少的内存,分配更少的临时对象。

线程和锁

线程可以持有锁,例如通过在一个对象上做同步。当多个线程协作时,可能会出现死锁,JProfiler可以为你可视化这种情况。 此外,锁可能被争用,这意味着线程在获得锁之前必须等待。通过JProfiler可以深入了解线程及其各种锁情形。

高层子系统

许多性能问题发生在更高的语义层面。例如,对于JDBC调用,你可能想找出哪条SQL语句是最慢的。 对于这样的子系统,JProfiler提供了"探针",将特定有效载荷附加到调用树。

JProfiler的UI是一个桌面应用程序。你可以以交互的方式实时分析JVM,也可以在不使用UI的情况下,自动化分析。 保存在快照中的分析数据,可以通过JProfiler UI打开。此外,命令行工具和构建工具集成可以帮助你自动分析会话。

⚡使用Jprofiler调试Dump文件

OOM错误

import java.util.ArrayList;

//-Xms  设置初始化内存大小,默认是1/64
//-Xms  设置最大分配内存,默认是1/4
//-XX:+PrintGCDetail    打印GC垃圾回收的相关信息
//-XX:+HeapDumpOnOutOfMemoryError   打印OOM的错误,并Dump
//-Xms1m -Xms8m -XX:+HeapDumpOnOutOfMemoryError
public class Demo03 {

    byte[] bytes = new byte[1*1024*1024];

    public static void main(String[] args) {
        ArrayList<Demo03> objects = new ArrayList<>();

        int count = 0;

        try {
            while (true) {
                objects.add(new Demo03());
                count++;
            }
        } catch (Exception e) {
            System.out.println(count);
            System.out.println(e.getMessage());
        }
    }
}

下载JProfiler

Jprofiler下载

无脑式下一步安装即可

然后IDEA下载 Jprofiler插件

在这里插入图片描述

下载完后程序我们去tools配置下载的客户端Jprofiler

IDEA会自动配置

在这里插入图片描述

在执行程序时加上以下参数

在这里插入图片描述

执行完毕后会dump下来文件

在这里插入图片描述

打开项目根目录找到dump文件

在这里插入图片描述

打开分析错误

在这里插入图片描述

二、堆内存调优

import java.util.Random;

public class Test {

    public static void main(String[] args) {
        //返回虚拟机试图使用的最大内存
        long max = Runtime.getRuntime().maxMemory();
        //返回虚拟机的初始化内存
        long totalMemory = Runtime.getRuntime().totalMemory();

        System.out.println("虚拟机试图使用的最大内存:" + max + "字节," + ((double)max/1024/1024) + "MB");
        System.out.println("虚拟机的初始化内存:" + totalMemory + "字节," + ((double)totalMemory/1024/1024) + "MB");

        //在启动时配置JVM参数
        //-Xms8m -Xms8m -XX:+PrintGCDetails

        //伊甸园区+老年区=堆内存  元空间 逻辑上存在,物理上不存在
        //305664K + 699392K = 1,005,056K = 981.5MB
        
        //默认情况下,分配的总内存 是电脑内存的 1/4 而初始内存是 1/64
        
        //OOM错误解决
        //1.尝试扩大堆内存,看结果
        //2.分析内存,看那个地方出现了问题(专业工具)
    }

}

在这里插入图片描述

设置JVM参数启动

import java.util.Random;

public class Test {

    public static void main(String[] args) {
        //返回虚拟机试图使用的最大内存
        long max = Runtime.getRuntime().maxMemory();
        //返回虚拟机的初始化内存
        long totalMemory = Runtime.getRuntime().totalMemory();

        System.out.println("虚拟机试图使用的最大内存:" + max + "字节," + ((double)max/1024/1024) + "MB");
        System.out.println("虚拟机的初始化内存:" + totalMemory + "字节," + ((double)totalMemory/1024/1024) + "MB");

        //-Xms8m -Xms8m -XX:+PrintGCDetails

        //伊甸园区+老年区=堆内存  元空间 逻辑上存在,物理上不存在
        //305664K + 699392K = 1,005,056K = 981.5MB
    }

}

设置JVM参数

在这里插入图片描述

单击 modiy options

在这里插入图片描述

选择JVM参数
在这里插入图片描述

写入参数名称

在这里插入图片描述

Apply同意并保存

执行代码

在这里插入图片描述

我们可以得出,伊甸园区内存大小+老年代内存大小=981.5

所以说,元空间,逻辑上存在,物理上不存在

三、 GC垃圾回收器

在这里插入图片描述

JVM在进行GC垃圾回收时,并不是对这三个区域同意回收,大部分回收都是新生代

  • 新生代
  • 幸存区(from to)
  • 老年区

GC两种类型:轻GC(普通的GC) 重GC(全局GC)

GC题目:

  • JVM的内存模型和分区,详细到每个区放什么?
  • 堆里面的区有哪些?Eden,form,to,老年区,说说他们的特点!
  • GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数器 怎么用的?
  • 轻GC和重GC分别在什么时候发生?

四、GC常用算法

❄️引用计数法

在这里插入图片描述

⛄复制算法

在这里插入图片描述

在这里插入图片描述

  • 好处:没有内存的碎片

  • 坏处:浪费了内存空间,多了一半空间永远是空的。假设对象100%存活(极端情况)

复制算法最佳使用场景:对象存活度较低的时候;新生区~

♨️标记清除算法

在这里插入图片描述

优点: 不需要额外的空间,把复制算法的缺点弥补了

缺点: 两次扫描严重浪费时间,会产生内存碎片,hash定位需要成本

⛽标记压缩

再次优化

在这里插入图片描述

⚠️标记清除压缩

先标记清除几次

在这里插入图片描述

再压缩

在这里插入图片描述

内存效率:复制算法 —> 标记清除算法 —> 标记压缩算法(时间复杂度)

内容整齐度:复制算法 = 标记压缩算法 —> 标记清除算法

内容利用率:标记压缩算法 = 标记清除算法 —> 复制算法

没有最优算法吗?

没有,没有最好的算法,只有最合适的算法, —> GC:分代收集算法

年轻代:

  • 存活率低
  • 复制算法

老年代:

  • 区域大:存活率高
  • 标记清除(内存碎片不是太多)+标记压缩混合实现

五、JMM

  1. 什么是JMM:Java Memory Model

  2. 它是干嘛的?:官方,博客,对应的视频

    作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到规则)

    JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存中(Main Memory)中,

    每个线程都有一个私有的工作内存(Local Memory)

在这里插入图片描述

​ 解决共享对象可见性的问题:volatile

  1. 它该如何学习

    ​ JMM是一个抽象的概念,理论

    可见性

    volatile关键字

​ 指令重排

关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步到主内存之间的实现细节,Java内存模型定义了以下八种操作来完成:

  • lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
  • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
  • load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
  • write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

Java内存模型还规定了在执行上述八种基本操作时,必须满足如下规则:

  • 如果要把一个变量从主内存中复制到工作内存,就需要按顺寻地执行read和load操作, 如果把变量从工作内存中同步回主内存中,就要按顺序地执行store和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。
  • 不允许read和load、store和write操作之一单独出现
  • 不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
  • 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
  • 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
  • 一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。lock和unlock必须成对出现
  • 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值
  • 如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
  • 对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

⛵小结

以上就是【Bug 终结者】对 【高级篇】Java JVM实战 之 内存调优 的简单介绍,JVM 内存优化,偏底层知识,认真研究,虚心进步,加油,走过的艰难终将铺向成功的道路,学习JVM可了解Java程序的运行方式以及运行原理,更深层次的理解可提高自己对Java知识再上高峰,JVM 内存调优,进阶必备!

如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!

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

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

相关文章

Spark 3.0 - 4.Pipeline 管道的工作流程

目录 一.引言 二.基本组件 三.Pipeline 基本流程 1.训练 Pipeline - Estimator 2.预测 Pipeline - Transformer 四.Pipeline 分解与构造 1.DataFrame 2.Transformer1 - Tokenizer 3.Transformer2 - HashingTF 4.Estimator - LR 5.Pipeline With ParamMap - Estimat…

SpringCloud微服务(一)——Consul服务注册中心

Consul服务注册中心 SpringCloud 中文官网&#xff1a;https://www.springcloud.cc/spring-cloud-consul.html Consul是一套开源的分布式服务发现和配置管理系统&#xff0c;Go语言开发。 Consul是一个服务网格&#xff08;微服务间的 TCP/IP&#xff0c;负责服务之间的网络…

SharedPreferences存储

文章目录 前言 听说SharedPreferences存储技术快过时了&#xff0c;不过如果是单纯的使用的话&#xff0c;不费什么时间成本。 本文的Demo摘录自《第一行代码》。 一.什么是SharedPreferences SharedPreferences&#xff0c;一种通过使用键值对的方式来存储数据的技术。 二…

【深入浅出Spring6】第八期——面向切面编程 AOP

AOP&#xff08;Aspect Oriented Programming&#xff09;面向切面编程&#xff0c;属于面向对象编程的一种衍射&#xff0c;是一种编程思想或技术AOP的底层是由动态代理机制实现的 JDK动态代理CGLIB动态代理&#xff0c;自动识别并切换我们也可以通过配置属性指定就是用CGLIB …

【MySQL】六,sql_model的合理设置

宽松模式和严格模式 宽松模式 如果设置的是宽松模式&#xff0c;那么我们在插入数据的时候&#xff0c;即使是给了一个错误的数据&#xff0c;那么可能也不会报错。 举例&#xff1a;某张表的name字段为 char(10) &#xff0c;插入数据的时候&#xff0c;如果name字段的数据长…

免费搜题系统

免费搜题系统 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击跳转&a…

跨模态神经搜索实践VCED 基于Streamlit实现前端页面设计和逻辑

1. Streamlit入门 1.1 Streamlit介绍 Streamlit是基于Python的Web应用程序框架&#xff0c;它可以使用Python代码轻松构建机器学习/数据科学相关的仪表板&#xff0c;其特点包括&#xff1a; 跨平台&#xff1a;支持Windows、macOS、Linux只需要掌握Python&#xff1a;不需要…

【时序】时间序列数据预处理

目录 1. 时间戳转换 2. 缺失值处理 3. 去噪 1&#xff09;滚动平均值 2&#xff09;傅里叶变换 4. 异常点检测 1&#xff09;基于滚动统计的方法 2&#xff09;孤立森林 3&#xff09;K-means 聚类 为了分析预处理结果&#xff0c;我们后续使用 Kaggle 的 Air Passenge…

【Python】发布一个简单好用的日志记录器bestlog

需求 日志是非常重要的一个东西&#xff0c;我们往往习惯于在开发一个新项目的第一行代码时&#xff0c;就用 logging.info 代替 print&#xff0c;随时保持记录的好习惯&#xff0c;等代码上线以后也无需修改替换那些 print&#xff0c;直接开跑&#xff0c;有了完善的日志&a…

牛客刷题——Python入门总结

&#x1f935;‍♂️ 个人主页: 北极的三哈 个人主页 &#x1f468;‍&#x1f4bb; 作者简介&#xff1a;Python领域优质创作者。 &#x1f4d2; 系列专栏&#xff1a;《Python入门学习》《牛客题库-Python篇》 &#x1f310;推荐《牛客网》——找工作神器|笔试题库|面试经…

【软考软件评测师】第三十章 操作系统(PV操作与死锁)

【软考软件评测师】第三十章 操作系统&#xff08;PV操作与死锁&#xff09; 第三十章 操作系统&#xff08;PV操作与死锁&#xff09;【软考软件评测师】第三十章 操作系统&#xff08;PV操作与死锁&#xff09;第一部分 知识点集锦1.PV操作1&#xff09;P操作的定义2&#xf…

win11的文件属性默认显示全部,Windows11右键菜单修改为Win10模式的方法(手把手详细操作)

win11的文件属性默认显示全部&#xff0c;Windows11右键菜单修改为Win10模式的方法&#xff08;手把手详细操作&#xff09; 文章目录win11的文件属性默认显示全部&#xff0c;Windows11右键菜单修改为Win10模式的方法&#xff08;手把手详细操作&#xff09;Tips 1 先以管理员…

Source Map知多少?Golang手写SourceMap转换过程

文章目录一、问题背景二、Source Map 简介基本格式应用场景三、Source Map 的工作原理四、Source Map 的转换过程代码示例总结本文从原理的角度入手对 Source Map 进行了较为深入的分析&#xff0c;并从业务需要的角度出发&#xff0c;手动编写根据 Source Map 映射编码前后代码…

SpringBoot集成Mybatis项目实操

本文为《从零打造项目》系列第三篇文章&#xff0c;首发于个人网站。 《从零打造项目》系列文章 比MyBatis Generator更强大的代码生成器 SpringBoot项目基础设施搭建 前言 基于 orm-generate 项目可以实现项目模板代码&#xff0c;集成了三种 ORM 方式&#xff1a;Mybatis、M…

35m预应力简支梁桥毕业设计 课程设计-桥梁工程(计算书、8张CAD图)

35m预应力简支梁桥毕业设计 目 录 1、引言 1 2、桥型方案比选 2 2&#xff0e;1 桥梁设计原则 2 2.2方案一&#xff1a;25m预应力钢筋混凝土T梁桥 2 2.3方案二&#xff1a;25m预应力钢筋混凝土小箱梁 4 2.4桥墩方案比选 4 3、上部结构设计计算 5 3&#xff0e;1 设计资料及构造…

考研数据结构填空题整合

考研数据结构填空题整合 目录考研数据结构填空题整合一、ZYL组ZYL组一ZYL组二ZYL组三ZYL组四ZYL组五ZYL组六ZYL组七ZYL组八二、TJP组TJP组一TJP组二TJP组三三、LZH组LZH 组一LZH 组二LZH 组三LZH 组四LZH 组五LZH 组六LZH 组七四、LB组LB组一LB组二LB组三LB组四LB组五LB组六LB组…

FPGA实现精简版UDP通信,占资源很少但很稳定,提供2套工程源码

目录1.高端、中等和精简版UDP通信的选择2.精简版UDP通信实现方案3.工程1介绍及资源占用率和性能表现4.工程2介绍及资源占用率和性能表现5.上板调试验证6.福利&#xff1a;工程代码的获取1.高端、中等和精简版UDP通信的选择 FPGA实现UDP协议可难可易&#xff0c;具体根据项目需…

Python 函数转命令行界面库 -- Argsense CLI

argsense 是一个 python 命令行界面库, 是 click, fire, typer 之外的又一个选项. argsense 最大的特点是极低的侵入性设计和近乎零成本的上手难度, 如果你熟悉 python 函数是如何传参的 (这是大部分 python 初学者已经掌握的知识), 那么你就可以很快上手 argsense. 特性一览 …

大数据(9e)图解Flink窗口

文章目录1、代码模板1.1、pom.xml1.2、log4j.properties1.3、Java模板2、按键分区&#xff08;Keyed&#xff09;、非按键分区&#xff08;Non-Keyed&#xff09;2.1、Keyed2.2、Non-Keyed3、窗口的分类3.1、基于时间的窗口3.2、基于事件个数的窗口4、窗口函数5、示例代码5.1、…

TIA博途_水处理项目中开启累计运行时间最短的泵_程序示例

TIA博途_水处理项目中开启累计运行时间最短的泵_程序示例 需求: 有N台水泵,每个水泵统计累计运行时间。当满足条件时,根据设定开泵的数量,启动累计运行时间最短的对应数量的泵。故障切换时,也切换到运行时间最短的泵。 具体方法可参考以下内容: 如下图所示,打开TIA博途后…