【jvm从入门到实战】(十) 实战篇-内存调优

news2024/9/24 20:03:14

内存溢出和内存泄漏:在Java中如果不再使用一个对象,但是该对象依然在GC ROOT的引用链上,这个对象就不会被垃圾回收器回收,这种情况就称之为内存泄漏。内存泄漏绝大多数情况都是由堆内存泄漏引起的。少量的内存泄漏可以容忍,但是如果发生持续的内存泄漏,就像滚雪球雪球越滚越大,不管有多大的内存迟早会被消耗完,最终导致的结果就是内存溢出。但是产生内存溢出并不是只有内存泄漏这一种原因

内存泄漏的常见场景:

  1. 内存泄漏导致溢出的常见场景是大型的Java后端应用中,在处理用户的请求之后,没有及时将用户的数据删除。随着用户请求数量越来越多,内存泄漏的对象占满了堆内存最终导致内存溢出。这种产生的内存溢出会直接导致用户请求无法处理,影响用户的正常使用。重启可以恢复应用使用,但是在运行一段时间之后依然会出现内存溢出。
  2. 第二种常见场景是分布式任务调度系统如Elastic-job、Quartz等进行任务调度时,被调度的Java应用在调度任务结束中出现了内存泄漏,最终导致多次调度之后内存溢出。这种产生的内存溢出会导致应用执行下次的调度任务执行。同样重启可以恢复应用使用,但是在调度执行一段时间之后依然会出现内存溢出。

解决内存溢出的步骤总共分为四个步骤:发现问题-通过监控工具尽可能早发现内存变大的现象、诊断原因-通过分析工具诊断产生的原因然后定位到问题代码、修复问题、测试验证

一、发现问题

1、发现问题的几个工具

1. Top命令

top命令是linux下用来查看实时查看系统资源的命令,比如执行时的进程、线程和系统参数等信息。
使用top命令后,展示的进程使用的内存为RES(常驻内存)- SHR(共享内存),按下M即可根据内存使用大小对进程进行排序。
缺点:只能查看最基础的进程信息,无法查看到每个部分的内存占用(堆、方法区、堆外)
在这里插入图片描述

2. VisualVM

是多功能合一的Java故障排除工具并且他是一款可视化工具,整合了命令行 JDK 工具和轻量级分析功能,功能非常强大。这款软件在Oracle JDK 6~8 中发布,但是在 Oracle JDK 9 之后不在JDK安装目录下需要单独下载。下载地址:https://visualvm.github.io/
优点:功能丰富,实时监控CPU、内存、线程等详细信息;支持Idea插件,开发过程中也可以使用
缺点:对大量集群化部署的Java进程需要手动进行管理
在这里插入图片描述

3. Arthas

Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
优点:功能强大,不止于监控基础的信息,还能监控单个方法的执行耗时等细节内容。
在这里插入图片描述

使用案例:使用阿里arthas tunnel管理所有的需要监控的程序

背景:
小李的团队已经普及了arthas的使用,但是由于使用了微服务架构,生产环境上的应用数量
非常多,使用arthas还得登录到每一台服务器上再去操作非常不方便。他看到官方文档上可
以使用tunnel来管理所有需要监控的程序。

步骤:
1.在Spring Boot程序中添加arthas的依赖(支持Spring Boot2),在配置文件中添加
tunnel服务端的地址,便于tunnel去监控所有的程序。
2.将tunnel服务端程序部署在某台服务器上并启动。
3.启动java程序
4.打开tunnel的服务端页面,查看所有的进程列表,并选择进程进行arthas的操作

4. Prometheus + Grafana

Prometheus+Grafana是企业中运维常用的监控方案,其中Prometheus用来采集系统或者应用的相关数据,同时具备告警功能。Grafana可以将Prometheus采集到的数据以可视化的方式进行展示。Java程序员需要学会读懂Grafana展示的Java虚拟机相关的参数。
优点:支持系统级别和应用级别的监控,比如linux操作系统、Redis、MySQL、Java进程。支持告警并允许自定义告警指标,通过邮件、短信等方式尽早通知相关人员进行处理

【重要】一般堆内存泄露的现象:
在这里插入图片描述

2、产生内存溢出原因一 :代码中的内存泄漏

在这里插入图片描述

案例1:equals()和hashCode()导致的内存泄漏(养成好的代码习惯就不会出现)

问题:在定义新类时没有重写正确的equals()和hashCode()方法。在使用HashMap的场景下,如果使用这个类对象作为key,HashMap在判断key是否已经存在时会使用这些方法,如果重写方式不正确,会导致相同的数据被保存多份。

解决方案:
1、在定义新实体时,始终重写equals()和hashCode()方法。
2、重写时一定要确定使用了唯一标识去区分不同的对象,比如用户的id等。
3、hashmap使用时尽量使用编号id等数据作为key,不要将整个实体类对象作为key存放。

案例2:内部类引用外部类(很少出现)

问题: 1、非静态的内部类默认会持有外部类,尽管代码上不再使用外部类,所以如果有地方引用了这个非静态内部类,会导致外部类也被引用,垃圾回收时无法回收这个外部类。
2、匿名内部类对象如果在非静态方法中被创建,会持有调用者对象,垃圾回收时无法回收调用者。

解决方案:
1、这个案例中,使用内部类的原因是可以直接获取到外部类中的成员变量值,简化开发。如果不想持有外部类对象,应该使用静态内部类。
2、使用静态方法,可以避免匿名内部类持有调用者对象。

案例3:ThreadLocal的使用(注意)

问题:如果仅仅使用手动创建的线程,就算没有调用ThreadLocal的remove方法清理数据,也不会产生内存泄漏。因为当线程被回收时,ThreadLocal也同样被回收。但是如果使用线程池就不一定了。
解决方案:线程方法执行完,一定要调用ThreadLocal中的remove方法清理对象。

案例4:String的intern方法(极少出现,一般在自主开发框架中产生)

问题:JDK6中字符串常量池位于堆内存中的Perm Gen永久代中,如果不同字符串的intern方法被大量调用,字符串常量池会不停的变大超过永久代内存上限之后就会产生内存溢出问题。
解决方案:1、注意代码中的逻辑,尽量不要将随机生成的字符串加入字符串常量池;
2、增大永久代空间的大小,根据实际的测试/估算结果进行设置-XX:MaxPermSize=256M

案例5:通过静态字段保存对象(开发中容易出现)

问题:如果大量的数据在静态变量中被长期引用,数据就不会被释放,如果这些数据不再使用,就成为了内存
泄漏。
解决方案:1、尽量减少将对象长时间的保存在静态变量中,如果不再使用,必须将对象删除(比如在集合中)或者将静态变量设置为null。
2、使用单例模式时,尽量使用懒加载,而不是立即加载。
3、Spring的Bean中不要长期存放大对象,如果是缓存用于提升性能,尽量设置过期时间定期失效。

案例6:资源没有正常关闭(可能出现,要养成好习惯)

问题:连接和流这些资源会占用内存,如果使用完之后没有关闭,这部分内存不一定会出现内存泄漏,但是会导致close方法不被执行。
解决方案:
1、为了防止出现这类的资源对象泄漏问题,必须在finally块中关闭不再使用的资源。
2、从 Java 7 开始,使用try-with-resources语法可以用于自动关闭资源。

3、产生内存溢出原因二 : 并发请求问题(极易出现)

并发请求问题指的是用户通过发送请求向Java应用获取数据,正常情况下Java应用将数据返回之后,这部分数据就可以在内存中被释放掉。

但是由于用户的并发请求量有可能很大,同时处理数据的时间很长,导致大量的数据存在于内存中,最终超过了内存的上限,导致内存溢出。这类问题的处理思路和内存泄漏类似,首先要定位到对象产生的根源。
可以自己使用Apache Jmeter软件可以进行并发请求测试。

案例 使用Jmeter进行并发测试,发现内存溢出问题

背景:
小李的团队发现有一个微服务在晚上8点左右用户使用的高峰期会出现内存溢出的问题,于是
他们希望在自己的开发环境能重现类似的问题。

步骤:

  1. 安装Jmeter软件,添加线程组。
  2. 在线程组中增加Http请求,添加随机参数。
  3. 在线程组中添加监听器 – 聚合报告,用来展示最终结果。
  4. 启动程序,运行线程组并观察程序是否出现内存溢出。

二、诊断

内存快照:

  • 当堆内存溢出时,需要在堆内存溢出时将整个堆内存保存下来,生成内存快照(Heap Profile )文件。使用MAT打开hprof文件,并选择内存泄漏检测功能,MAT会自行根据内存快照中保存的数据分析内存泄漏的根源。
    在这里插入图片描述

  • 生成内存快照的Java虚拟机参数:
    -XX:+HeapDumpOnOutOfMemoryError:发生OutOfMemoryError错误时,自动生成hprof内存快照文件。
    -XX:HeapDumpPath=<path>:指定hprof文件的输出路径。

《jvm从入门到实战》就学到这(P1-P52),后面很多原理和实操,需要的时候再看。

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

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

相关文章

MySQL5.x与8.0

大致区别 1. 性能&#xff1a;MySQL 8.0 的速度要比 MySQL 5.7 快 2 倍 MySQL 8.0 在以下方面带来了更好的性能&#xff1a;读/写工作负载、IO 密集型工作负载、以及高竞争&#xff08;"hot spot"热点竞争问题&#xff09;工作负载2. NoSQL&#xff1a;MySQL 从 5.7 …

CPU算力分配 - 华为OD统一考试

OD统一考试 题解: Java / Python / C++ 题目描述 现有两组服务器A和B,每组有多个算力不同的CPU,其中 A 是A组第个CPU的运算能力,是 B组 第个CPU的运算能力。一组服务器的总算力是各CPU的算力之和。 为了让两组服务器的算力相等,允许从每组各选出一个CPU进行一次交换。 求…

基于PHP的蛋糕购物商城系统

有需要请加文章底部Q哦 可远程调试 基于PHP的蛋糕购物商城系统 一 介绍 此蛋糕购物商城基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销…

做一个wiki页面是体验HTML语义的好方法

HTML语义&#xff1a;如何运用语义类标签来呈现Wiki网页 在上一篇文章中&#xff0c;我花了大量的篇幅和你解释了正确使用语义类标签的好处和一些场景。那么&#xff0c;哪些场景适合用到语义类标签呢&#xff0c;又如何运用语义类标签呢&#xff1f; 不知道你还记不记得在大…

爱芯派pro通过无线网卡rtl8188eu连接热点

爱芯派pro通过无线网卡rtl8188eu连接热点 爱芯派pro目前的底板的pcie的复位有问题&#xff0c;所以pcie接口无法挂载上去&#xff0c;所以自己购买的rtl8822网卡也用不了&#xff0c;然后想起来自己还有正点原子的rtl8188eu网卡&#xff0c;但是没有和工作人员进行摸索后才知道…

Swagger升级指南:Swagger2与Swagger3注解差异揭秘

在API开发的世界里&#xff0c;Swagger已经成为了一个不可或缺的工具&#xff0c;它让API的文档化和前后端的协作变得前所未有地简单。随着Swagger的进化&#xff0c;我们迎来了Swagger3&#xff0c;也被称为OpenAPI Specification 3.0。本篇博客将带大家深入了解Swagger2和Swa…

【Python 基础】-- 在 mac OS 中安装 多个 python 版本

目录 1、需求 2、实现 2.1 安装 pyenv 2.2 安装 pyenv-virtualenv 2.3 配置环境变量 2.4 创建 python 3.9.9 的环境 2.5 激活环境&#xff0c;在当前项目目录中使用&#xff0c;即执行 python 1、需求 由于项目所依赖的 python 版本有多个&#xff0c;需要在不同的 pyth…

在线客服系统中的全渠道服务:多渠道整合与无缝沟通体验

很多采购人员在了解在线客服系统的时候都会遇到一个名词——全渠道。很多人第一次接触可能并不理解它是什么意思&#xff0c;也不知道自己的企业是否需要这个”全渠道“。今天这篇文章就为大家解答一二。 一、全渠道是什么&#xff1f; 全渠道 (Omni-Channel)&#xff0c;就是…

DeepLabV3+实现sar影像海面溢油区识别

今天我们分享DeepLabV3的sai影像水体提取。 数据集 本次使用的数据集是Deep-SAR Oil Spill (SOS) dataset。该数据集由中国地质大学的朱祺琪团队制作并共享。该数据集包含墨西哥湾溢油区域和波斯湾溢油区域&#xff0c;分别获取于ALOS 和Sentinel-1A卫星。由ECHO研究组搜集制作…

说说 Spring Boot 实现接口幂等性有哪几种方案?

一、什么是幂等性 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂等…

【go语言】error错误机制及自定义错误返回类型

简介 Go 语言通过内置的 error 接口来处理错误&#xff0c;该接口定义如下&#xff1a; type error interface {Error() string }这意味着任何实现了 Error() 方法的类型都可以作为错误类型。在 Go 中&#xff0c;通常使用 errors 包的 New 函数来创建简单的错误&#xff1a;…

三维尺寸中,您需要了解的设备及其特点

三维尺寸测量需要用到一些精密仪器&#xff0c;它们都有各自的特点。那么三维尺寸测量中常用的设备有哪些&#xff1f; 1、三坐标测量机 三坐标测量机即三坐标测量计算机数控系统&#xff0c;是一种高精度的测量设备。除了传统的点、线、面和圆柱体等基本轮廓外&#xff0c;还可…

车辆违规实线变道检测系统:融合Gold-YOLO改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着城市化进程的加快和交通工具的普及&#xff0c;道路交通安全问题日益凸显。其中&#xff0c;车辆违规实线变道是导致交通事故的重要原因之一。在道路上&…

游戏引擎?

游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具&#xff0c;其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始。大部分都支持多种操作平台&#xff0c;如Linux、…

【STM32工具篇】使用CLion开发STM32

本文主要记录使用CLion开发STM32&#xff0c;并调试相关功能 使用的CLion版本&#xff1a;2023.3.1 CLion嵌入式配置教程&#xff1a;STM32CubeMX项目 |CLion 文档 (jetbrains.com) OpenOCD官网下载&#xff1a;Download OpenOCD for Windows (gnutoolchains.com) GNU ARM工…

【物联网无线通信技术】WiFi从理论到实践(ESP8266)

文章从理论基础到具体实现完整的介绍了最常见的物联网无线通信技术&#xff1a;WiFi。 文章首先介绍了WiFi这种无线通信技术的一些基本概念&#xff0c;并针对其使用的802.11协议的基本概念与其定义的无线通信连接建立过程进行了简单的介绍&#xff0c;然后对WiFi开发常常涉及的…

基于YOLOv5的吸烟检测系统设计与实现

一、项目背景 吸烟检测作为保障公共健康和环境安全的重要任务之一&#xff0c;一直备受关注。传统的吸烟检测方法往往依赖人工判断&#xff0c;存在准确性低和实时性差的问题。为了解决这些问题&#xff0c;本项目基于深度学习技术进行了吸烟检测系统的设计与实现&#xff0c;…

VMware vSphere 虚拟机迁移按钮灰色解决方案

现象&#xff1a;在 vCenter Server 中右键单击虚拟机&#xff0c;然后单击迁移时&#xff0c;迁移选项将灰显。 原因&#xff1a;在虚拟机备份完成后&#xff0c;没有移除 vCenter Server 数据库 vpx_disabled_methods 表中的条目时&#xff0c;可能会出现此问题。 解决方案&a…

【Transformer框架代码实现】

Transformer Transformer框架注意力机制框架导入必要的库Input Embedding / Out EmbeddingPositional EmbeddingTransformer EmbeddingScaleDotProductAttention(self-attention)MultiHeadAttention 多头注意力机制EncoderLayer 编码层Encoder多层编码块&#xff0f;前馈网络层…

【ARM Trace32(劳特巴赫) 高级篇 21 -- Trace 系统性能分析 Performance Analyzer】

请阅读【Trace32 ARM 专栏导读】 文章目录 Performance AnalyzerPerf 操作步骤采样对象PC采样对象Memory采样对象 TaskPerformance Analyzer sample-based profiling 通常也叫做Trace32 的性能分析(Perf), 这个功能是通过周期性的采样来实现的。被采样到的数据可以被用于统计…