为什么会出现内存泄漏?

在计算机的组件中,内存是非常重要的存在。在做性能测试的过程中,针对内存的监控也是非常核心的一类指标项。在一些场景的沟通中,发现大家对于内存的理解可能存在一些偏差。本文结合笔者的经验,对内存做一些基础知识的汇总。

01

为什么会有内存的存在?

在冯.诺依曼结构的核心设计思想中,计算机的五个基本组成部分:运算器、控制器、存储器、输入设备、输出设备。其中的存储器指主要功能是存储程序和各种数据,并且能够在计算机运行过程高速、自动地完成程序或者数据的存储。存储器可以分为内部存储器(内存)和外部存储器(硬盘)。

早期的内存是固化在主板上,可存储的数据有限。随着CPU的工艺技术不断发展,速度越来越快(I7的CPU,主频可达到2.69GHz)),但是硬盘由于机械结构的局限性(读写速度120MB/S),无法跟上CPU的节奏,从而造成CPU资源的闲置。于是就有的独立的内存(读写速度大约在7~9GB/s),用于把常用数据从硬盘中读取出来(Cached ),供CPU快速使用,同时,把经CPU处理过的数据暂存在内存中(Buffers),后续再固化到硬盘中。

这个过程是不是很像我们现在的 业务 —> redis —> 数据库的结构

02

为什么会出现内存泄漏?

如上图所示,不同操作系统对于内存的管理机制也是不一样的。简单来说,Windows对于内存的管理就是省着用,而对于Lixnu来说,就是能用多少就用多少,尽可能用。

03

在性能测试过程中,我们对于Linux操作系统的内存查看,一般会通过Free命令来看,如下图所示,在算可用内存的时候,是free+buff/cache,而不单单只看free的值。因为buff/cache在需要的时候,可以快速被释放,变成内存使用。也可以通过命令来手动释放这类内存。

echo 3 >proc/sys/vm/drop_caches

为什么会出现内存泄漏?

那么,在Linxu中,内存什么时候真的不够用了呢?就是Swap有值了,Swap指的是硬盘上交换分区的使用大小。设计的目的就是当上面提到的+buffers/cache表示的可用内存都已使用完,新的读写请求过来后,会把内存中的部分数据写入磁盘,从而把磁盘的部分空间当作虚拟内存来使用。

04

那我们通常所说的内存泄漏又指的是什么呢?

内存泄漏一般指的是某个对象的引用丢失,无法再访问到该引用,但是该引用却依旧引用着某个对象,导致这个对象无法回收,最终导致内存溢出OOM。简单而言,就是内存里的对象无法被引用,也无法被回收,一直占用着不释放,导致内存的可使用量减少。在面试过程中,如果没有特别说明,内存泄漏指的是JVM内存的泄露(JAVA是当下企业的主流研发语言,所以一般情况下探讨的是这类问题,其他语言当然也存在,但是相对来说没那么严重,原因是其他语言都是直接使用物理内存,量比较大,而JAVA使用的是JVM内存,一般都只会设置在2G左右,过高会严重影响GC效率,导致服务不可用)。

那么,如何判断JVM是否存在泄露呢?目前主流的工具(Visualvm、jstack、Jprofiler等)都会提供相对应的功能,在发生GC的时候,如果发现每次GC的量在不断地变小,且GC的频率越来越快,那么就有可能是内存泄露了。这个时候就需要去看看JVM里存放了哪些大对象。(关于GC,推荐阅读一文搞懂JVM新生代、老年代和永久代



我的回答