一、背景介绍
AR项目有一个爬取的功能,之前出现了爬取加载慢的情况,经过排查发现服务的内存占用非常高。下面一起分析内存过高的问题
二、实现思路
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
在linux系统上我们可以通过名称生成dump文件,将生成的dump文件下载到本地运行内存分析工具进行分析。
jmap -dump:[live,]format=b,file=<filename> <pid>
在windows系统上我们可以直接打开内存分析工具,然后运行程序。就可以看到内存飙升的情况。
GC清理了堆内的对象,但没有及时把内存归还给操作系统
对于内存归还的的触发和垃圾回收器及其回收机制有关系,可以通过命令查看jvm目前使用的是哪一种垃圾回收器。
java -XX:+PrintCommandLineFlags -version
四、其他情况
内存泄漏:内存泄漏是指程序中已分配的内存没有被正确释放,导致这部分内存无法再被其他程序使用。常见的内存泄漏情况包括未及时释放资源、循环引用等。
大对象或大数据集:如果程序中存在大对象或大数据集,会占用较多的内存空间。特别是在处理图像、视频、大型文件等场景下,需要注意内存的使用情况。
频繁创建和销毁对象:如果程序中频繁创建和销毁对象,会导致内存占用增加。特别是在循环或递归操作中,如果每次迭代都创建新的对象而不进行复用,会导致内存占用过高。
五、如何解决
内存泄漏检测和修复:通过使用内存泄漏检测工具,定位和修复内存泄漏问题。确保程序中分配的内存能够被正确释放。
对象池和对象复用:使用对象池技术,提前创建一定数量的对象并保存在池中,需要时从池中获取对象并使用,使用完后放回池中供其他请求使用。避免频繁创建和销毁对象,减少内存占用。
缓存数据:对于一些频繁使用的数据,可以将其缓存起来,避免重复创建对象。使用缓存库或自定义缓存机制来实现数据的缓存,减少内存占用。
优化算法和代码逻辑:通过优化算法和代码逻辑,减少不必要的对象创建和内存占用。避免在循环中创建对象,尽量使用基本数据类型代替包装类型等。
分页加载和懒加载:对于大数据集或大对象,可以采用分页加载或懒加载的方式,只在需要时加载部分数据,减少内存占用。
六、总结提升
对于内存飙升的问题我们可以通过压测的方式进行复现问题,根据内存分析工具聚焦到是哪一部分的问题,然后针对相应的进行代码的优化。也可以根据使用场景来选择对应的垃圾回收器和对应的机制
解决内存升高的问题需要注意内存泄漏的检测和修复,使用对象池和对象复用技术,缓存数据,优化算法和代码逻辑,以及采用分页加载和懒加载的方式。通过这些方案,可以有效减少内存占用,提高系统的性能和稳定性。