对于内存泄漏问题的简单认知

看了很多别人对内存泄漏和内存溢出的讲解,也看到很多对别人观点的辩驳。但可能正是因为看的太多了,总感觉有点乱,所以还是自己总结下好。下面是我对于内存泄漏的粗浅认识。

一、内存泄漏简介

首先要明确在计算机编程中,内存泄漏并非是指内存在物理上的消失。而是在应用程序分配了某段内存之后,由于设计错误或是某些不明确的bug,导致应用程序在未释放该段内存之后就失去了对该段内存的控制,从而造成了内存的浪费。

一些黑客能通过一段攻击代码来攻击能被公众访问的网络服务器或路由器等,使之产生内存泄漏或内存溢出

二、内存泄漏的后果

内存泄漏最直接的表现就是导致计算机或服务器性能降低,但是一般不会马上引起严重的状况。

需要明确的是,内存消耗持续增加不一定表明是内存泄漏,可能是有其他原因引起的。如程序设计者在设计程序时假设存储器总是足够运行特定的工作,而申请不合理的大量存储器。

这是由于大多数的现代计算机操作系统都有存储在RAM芯片中主内存和存储在次级存储设备如硬盘中的虚拟内存,内存分配是动态的——每个进程根据要求获得相应的内存。

访问活跃的页面文件被转移到主内存以提高访问速度;反之,访问不活跃的页面文件被转移到次级存储设备。当一个简单的进程消耗大量的内存时,它通常占用越来越多的主内存,使其他程序转到次级存储设备,使系统的运行效率大大降低。

甚至在有内存泄漏的程序终止后,其他程序需要相当长的时间才能切换到主内存,恢复原来的运行效率。

注意:第一个遭遇内存问题的程序不一定是引起内存泄露的程序,需要经过具体排查来确定是哪个程序或进程导致的内存泄漏

内存泄漏在以下场景当中会显得很严重:

  • 程序运行后就置之不理(比如服务器的后台任务)
  • 频繁的分配新内存(比如游戏运行)
  • 程序中止之后也不会被释放的内存(例如共享内存)
  • 剩余内存有限的时候
  • 系统关键驱动发生内存泄漏

三、容易引起内存泄露的操作

Java等语言中的垃圾回收机制能有效防止内存泄漏,像在没有垃圾回收的编程语言,如C和C++中,存储器泄露是很常见的错误(不过这两种语言有垃圾回收的库)

——垃圾回收
垃圾回收的设计思想,就是用不同级别的“访问性”来标识存储器中的对象,存储器管理器按照释放级别来优先释放访问性较低的对象。
强引用的对象或者间接和一组强引用相关的对象就表示该对象的访问性较强

虽说Java有GC,但并不是就此安然无恙,稳如老狗了。以下这些这些场景不注意的话,还是容易造成内存泄漏问题的:

  • 静态集合类的使用(例如 HashMap、Vector),这些静态变量的生命周期和应用程序的生命周期一致。 可以使用 jdk8 中ConCurrentHashMap类(据说这个类还是有内存泄漏的风险,jdk9好像解决了,这个可以自行去了解)。

  • 监听器。 释放对象的时候记得删除监听器

  • 各种资源的连接没有释放关闭(如数据库连接、网络连接等)。

  • 循环中创建大量无用对象

  • 泛用单例模式,在单例模式中持有外部对象的引用

  • 内部类和外部模块的引用

四、如何减少内存泄漏的发生

笔者的建议如下:
1. 平时养成良好的编程习惯,这是最重要的

2. 寻求测试工具的帮助

3. 注意 事件监听、回调函数、静态集合对象这几个内存泄漏大户

分享一篇有趣的文章内涵系列 | 30 张令程序员泪流满面的趣图

猜你喜欢

转载自juejin.im/post/5cb5d6adf265da03761e80fc