案例20-内存长期占用导致系统慢

简介: 内存长期占用导致系统慢

一、背景介绍

       AR项目有一个爬取的功能,之前出现了爬取加载慢的情况,经过排查发现服务的内存占用非常高。下面一起分析内存过高的问题

36dd901671c04f39ba57cffbae9d4f11.png

dba9adcf7a5149f6867f0f6edf35a412.png

二、实现思路

       1.服务启动分配堆内存过

       2.有大量的对象被创建

       3.GC清理了堆内的对象,但没有立即把内存归还给操作系统

三、实现过程

服务启动内存分配过小

       我们在启动服务的时候经常会配置Xms和Xmx的配置,例如:nohup java -Xms3072m -Xmx4096m -jar a.jar& 。

       -Xms 为JVM启动时申请的初始Heap值,默认为操作系统物理内存的1/64但小于1G。默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRation来指定这个比列。

       -Xmx 为JVM运行时可申请的最大Heap值,默认值为物理内存的1/4但小于1G,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation来指定这个比列

有大量的对象被创建

       通过监控内存飙升的那一时刻使用内存分析工具来对dump文件进行分析。找到内存飙升的原因并针对性的做出调整。

内存分析工具:jdk1.8自带的工具-jvisualvm.exe

0c5eeedc004348e69d86447c43710d82.png

在linux系统上我们可以通过名称生成dump文件,将生成的dump文件下载到本地运行内存分析工具进行分析。

jmap -dump:[live,]format=b,file=<filename> <pid>

在windows系统上我们可以直接打开内存分析工具,然后运行程序。就可以看到内存飙升的情况。

9910b203f64141e9998a8c197a2bdf81.png

b1a4844ac8bd4854841eaf374bdd38dc.png

7f19700e2ff242c9a5722398d8197059.png

GC清理了堆内的对象,但没有及时把内存归还给操作系统

对于内存归还的的触发和垃圾回收器及其回收机制有关系,可以通过命令查看jvm目前使用的是哪一种垃圾回收器。

java -XX:+PrintCommandLineFlags -version

7b60c54aade745c784abf200e2b6da83.png

四、其他情况

内存泄漏:内存泄漏是指程序中已分配的内存没有被正确释放,导致这部分内存无法再被其他程序使用。常见的内存泄漏情况包括未及时释放资源、循环引用等。

大对象或大数据集:如果程序中存在大对象或大数据集,会占用较多的内存空间。特别是在处理图像、视频、大型文件等场景下,需要注意内存的使用情况。

频繁创建和销毁对象:如果程序中频繁创建和销毁对象,会导致内存占用增加。特别是在循环或递归操作中,如果每次迭代都创建新的对象而不进行复用,会导致内存占用过高。

五、如何解决

内存泄漏检测和修复:通过使用内存泄漏检测工具,定位和修复内存泄漏问题。确保程序中分配的内存能够被正确释放。

对象池和对象复用:使用对象池技术,提前创建一定数量的对象并保存在池中,需要时从池中获取对象并使用,使用完后放回池中供其他请求使用。避免频繁创建和销毁对象,减少内存占用。

缓存数据:对于一些频繁使用的数据,可以将其缓存起来,避免重复创建对象。使用缓存库或自定义缓存机制来实现数据的缓存,减少内存占用。

优化算法和代码逻辑:通过优化算法和代码逻辑,减少不必要的对象创建和内存占用。避免在循环中创建对象,尽量使用基本数据类型代替包装类型等。

分页加载和懒加载:对于大数据集或大对象,可以采用分页加载或懒加载的方式,只在需要时加载部分数据,减少内存占用。

六、总结提升

        对于内存飙升的问题我们可以通过压测的方式进行复现问题,根据内存分析工具聚焦到是哪一部分的问题,然后针对相应的进行代码的优化。也可以根据使用场景来选择对应的垃圾回收器和对应的机制


       解决内存升高的问题需要注意内存泄漏的检测和修复,使用对象池和对象复用技术,缓存数据,优化算法和代码逻辑,以及采用分页加载和懒加载的方式。通过这些方案,可以有效减少内存占用,提高系统的性能和稳定性。


相关文章
|
存储 编译器 Go
Go 语言内存逃逸案例
Go 语言内存逃逸案例
58 0
|
3月前
|
NoSQL 程序员 Linux
轻踩一下就崩溃吗——踩内存案例分析
踩内存问题分析成本较高,尤其是低概率问题困难更大。本文详细分析并还原了两个由于动态库全局符号介入机制(it's a feature, not a bug)触发的踩内存案例。
|
7月前
|
Java
堆内存的溢出案例分析
堆内存的溢出案例分析
29 0
|
XML 存储 监控
JVM记一次PermGen space内存溢出实战案例
JVM记一次PermGen space内存溢出实战案例
92 0
|
7月前
|
存储 负载均衡 算法
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
109 2
|
7月前
|
缓存 Dubbo Java
案例 1: 某财险承保系统内存泄漏问题
案例 1: 某财险承保系统内存泄漏问题
|
4月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
392 0
|
2月前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
64 1
|
2月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。