案例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

四、其他情况

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

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

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

五、如何解决

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

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

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

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

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

六、总结提升

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


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


目录
打赏
0
0
0
0
6
分享
相关文章
Go 语言内存逃逸案例
Go 语言内存逃逸案例
89 0
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
650 7
轻踩一下就崩溃吗——踩内存案例分析
踩内存问题分析成本较高,尤其是低概率问题困难更大。本文详细分析并还原了两个由于动态库全局符号介入机制(it's a feature, not a bug)触发的踩内存案例。
堆内存的溢出案例分析
堆内存的溢出案例分析
65 0
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数
169 2
|
2月前
|
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
252 55
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
142 6
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
239 29
JVM简介—1.Java内存区域

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等