当前位置:首页 > 内存 > 正文

top查看内存泄漏(内存泄漏和内存溢出)

  • 内存
  • 2024-08-23 04:26:14
  • 2330

一、Linux下如何定位JAVA进程直接内存的泄漏及top和jmap查看内存的关系问题1:top的​​RES值和JAVA堆内存有什么关系?
——大约一两个月前有一篇文章讲过这件事。它很长,但我无法立即找到它。一般来说,很难找到非常精确的匹配计算关系。二、因为两个Calibre的统计数据不同;操作系统关心应用程序占用了什么,而JVM只关心堆中分配了什么;内存无法使用并且某些内存已在使用中。
——总的来说,我觉得如果不是为了基础发展等问题,不值得对这个问题进行深入研究。
问题2:如何直接在JAVA进程中定位内存泄漏?
​——不幸的是,没有办法直接确定它,否则内存泄漏就不会成为让人害怕的问题了;不同的工具只能为您提供某些方法来检测迹象并缩小怀疑范围(如果有)。如果它不能直接帮你定位自己,那听起来就像是一个神话而不是IT。
——常见的技巧是:范围和程度。两个方向通过测试和监控不断缩小怀疑范围,最终识别内存泄漏。
二、C++内存管理及内存问题的分析在服务器编程中,内存管理是一个不可避免的问题,尤其是在C++中,这个问题更加突出。进程的内存持续增长,这可能是由于正常使用、内存碎片,或更可能是内存泄漏,这需要我们采取技术来检测和修复它。
1.内存使用情况
从“top”指令开始,我们可以看一下与进程内存相关的两个指标:VIRT(虚拟内存)和RES(驻留内存)。VIRT代表整个进程请求的内存,包括程序本身以及new、malloc等分配的内存。RES是指主板上内存模块中进程占用的物理内存。虚拟内存的存在是因为C++无法直接管理硬件,必须通过操作系统来管理内存。现代计算机运行多个程序,每个程序独立运行。直接使用物理内存可能会导致资源争用。这样,操作系统通过内核管理物理内存,并为各个进程提供虚拟内存来实现内存管理。
2.内存泄漏
内存泄漏是进程内存不断增加的常见原因。这也是C++中常见但难以解决的问题。要解决这个问题,需要根据实际情况进行分析和处理。
3.内存碎片
如果排除了内存泄漏,那么我们就可以考虑内存碎片的问题了。以Linux的ptmalloc为例,当进程分配和释放内存时,就会出现内存碎片。内存碎片会导致进程占用更多内存,但实际使用的内存并不多。要检测内存碎片,可以使用malloc_stats或malloc_info等工具。
4.内存使用情况
如果进程使用的内存量明显高于预期,但没有继续增加,您可能需要考虑内存使用情况。例如,当使用new分配小内存时,系统需要记录该分配的大小、地址并分配对齐的内存。如果分配的内存很小,系统最终将消耗比实际分配的更多的内存。为了解决这个问题,可以使用valgrindmassif等工具来分析内存。
三、cgroup内存泄露问题排查记录发生内存泄漏的服务器是集群机器。已经运行5天左右,内存使用率超过90%。其上运行Docker和集群管理软件,并执行测试脚本以连续启动和停止。容器。
集群服务器长时间运行后,内存占用逐渐增加,出现应用程序OOM。
物理检查发现服务器总内存使用率较高,但应用程序实际内存使用率较低或未发现明显异常。
可以看到内存使用率为83.6%,而顶部显示的实际内存使用率最多仅为0.6%。
内存占用除了用户应用占用之外,还包括内核占用,所以要检查内核内存占用。
使用linux文件系统界面查看
可以看到容量极高的表项都被Slab内核占用了:
继续查看详细的内核占用状态,按照缓存大小排序
可以在这里看到:
kmalloc-2048,kmalloc-4096,kernfs_node_cache,kmalloc-1024,kmalloc-192、kmalloc-512占用的面积都比正常主机高,已经严重超出正常值。
如果内核缓存过高,可以尝试释放内核缓存:
但是,执行上述操作后,内存使用量仍然没有明显减少,也保持一致上面看到SUnreclaim:2447108kB//slab不可回收内存大小。该内存无法释放。
kmalloc是内核分配的内存。参考值kernfs_node_cache使用率很高,所以我搜索了它的能。
很明显,这个现象是内核使用严重超标,所以我在搜索中添加了Memoryleak关键字,很快就找到了Issuesdocker-run--memoryslabcacheleakoncentos7
这个问题表明centos7反复出现运行dockerrun--rm--memory1ghello-world时,内核内存使用量大幅增加且无法释放。而这个现象也和现在的现象是一致的。
最后,指向kernelcgroup内部内存泄漏问题,导致使用kmemcontrolgroup时出现问题
一般原因是在kernel3.10上使用kmemlimit参数,导致部分分配的内存无法释放在cgroup回收期间。想要更深入的了解,首先需要再花一些时间来解决手头的问题。
可能的原因已确定。重新定义这个问题,如果用上面的方法都能解决,就可以认定是一个问题。
在只运行docker的机器上执行上述命令,查看刀片内存使用情况可以看到内存使用量明显增加。并且最终的表现符合当前环境下的问题。总内存使用率高,用户态内存使用率低,内核内存使用率高且无法释放。
由于这是内核问题,而且重复路径是清楚的,所以可以通过两种方式解决:
最后经过测试,我选择了更改内核版本,Ubuntu18.04将被用作新的操作系统。
Linux内核使用分层内存管理方法。每个班级解决不同的问题。从下到上主要部分如下:
Slab是Linux操作系统的一种。内存分配机制。它的工作是针对某些经常分配和释放的对象,例如进程描述符。这些物体的尺寸一般都比较小。如果直接采用合伙人制度进行分配和释放,不仅会造成很多内部问题。碎片化和处理速度也会很慢。lab分配器是基于对象来管理的。相同类型的对象被分为一个类别(例如进程描述符)。每当应用这样的对象时,slab分配器就会从slab列表中分配一个该大小的对象。将关闭,当需要释放它时,它将保留在该列表中,而不是直接返回到合作伙伴系统,从而避免这些内部碎片。平板分配器不会处理分配的对象,而是释放它们并将其存储在内存中。当以后需要新的对象时,可以直接从内存中检索,无需重新初始化。
Slab占用内存过高。有以下含义: