相关历史文章(阅读本文之前,您可能需要先看下之前的系列 )

色谈Java序列化:女孩子慎入 - 第280篇

烦不烦,别再问我时间复杂度了:这次不色,女孩子进来吧 - 第281篇

双向链表,比西天还远?- 第282篇

面试不再怕,让LRU无处可逃 - 第283篇

爱我,就要懂我 – Memcached- 第284篇

内存管理,难于上青天?- memcached - 第285篇

你懂她,可惜你不懂我「LRU 」- Memcached- 第286篇

分布式算法真是吊炸天 – memcached- Memcached - 第287篇

悟纤:师傅,什么是内存泄露、内存溢出、内存碎片化?
师傅:徒儿,你问题有点小多呐,要不这次你自己探索下?
悟纤:好的,师傅徒儿这就去探索下。
师傅:那你去探索下吧,重点了解下内存碎片化。
悟纤:徒儿这就去,筋斗云..
师傅:徒儿…百度就可以了。

「话还没出口,悟纤已经到了十万八千里了。」

一、内存区

悟纤:要想了解内存泄露之类的,需要先查查数据存在哪里吧?
悟纤:嗯、很有道理,这就走起。

在内存中供用户使用的内存区有:静态存储区、动态存储区、程序存储区。

悟纤:啥是静态存储区?这个我得去查查。

静态存储区:内存在程序编译的时候就已经分配好,这块内存在整个计算机内存中位于较低的地址,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

悟纤:要理解动态存储区,要先理解下动态存储分配。

动态存储分配:在目标程序或操作系统运行阶段动态地为源程序中的量分配存储空间,动态存储分配包括栈式或堆两种分配方式。

动态存储区:允许目标程序或操作系统运行阶段动态地为源程序中的量分配的内存空间就是动态存储区。

悟纤:那程序存储区就是存放程序语句的,我真是太棒了。
悟纤:师傅,我探索的怎么样?
师傅:不错,不错,继续不要停。

二、泄露/溢出/碎片

悟纤:吃饱喝足,继续研究。

2.1 内存泄露

动态存储区一般是在程序运行过程中根据需要动态去分配和释放的内存区域。这块内存区域需要开发人员在使用完毕之后进行释放,如果没有释放动态分配的内存区域就会造成内存泄漏。相应的这块区域也不能够被使用。

BTW:简单来说,就是你使用了一块内存区域,但是却没有释放,那么这块内存区域谁都用不了了,这就是内存泄漏。

2.2 内存溢出

当一个程序向系统申请的所需内存大于系统可提供使用的内存时,这个时候就会产生内存溢出。

举个例子:有一个可以装50ml水的空杯子,但是你非得向这个被子里面倒了100ml水,那么这个时候多余的水肯定会流出来,这就是水溢出了。那么放到内存来讲,就是内存溢出。

BTW:内存泄漏积累到一定程度,会占用很多内存资源,从而导致内存溢出。

2.3 内存碎片

内存碎片分为外部碎片和内部碎片。

(1)外部碎片

外部碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。

产生的原因:外部碎片是出于任何已分配区域或页面外部的空闲存储块。这些存储块的总和可以满足当前申请的长度要求,但是由于它们的地址不连续或其他原因,使得系统无法满足当前申请。

(2)内部碎片

内部碎片就是已经被分配出去(能明确指出属于哪个进程)却不能被利用的空间。

产生原因:由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免。

三、内存碎片产生原因及解决办法

3.1 产生原因分析

使用最原始的标记分配方法:系统通过维护一个内存信息表来管理内存的状态。如下:

(1)当程序申请一个长度为3的内存空间后:

(2)当程序再申请一个长度为2,以及长度为4的内存空间后:

此时,只剩1个可用空间。如果这时程序再来申请长度大于1的空间,就申请不了,也就是内存不够。

(3)现在,释放掉ID=2的空间:

我们发现,现在可用内存空间为3,但是,这3个空闲空间,并不是连续的。所以,如果程序现在申请长度为3的内存空间,同样会申请不了,会出现内存不够。业界把这种情况,称之为【内存碎片】。

3.2 解决方法

明明剩余有3个空间,却申请不了3个内存空间???

于是,工程师们,发明了基于页面的内存管理方式:首先,把物理内存,按照某种尺寸,进行平均分割。

(1)比如我现在以2个内存单位,来分割内存,也就是每两个连续的内存空间,组成一个内存页:

(2)接着,程序再申请长度为1,长度为2的空间:

(3)释放掉ID=2,内存页ID为3的那条内存空间信息:

(4)现在,就出现了之前的情况:目前一共有4个内存空间,但是不连续。不过,因为现在是分页管理机制,因此,现在仍然可以继续申请长度为4的内存空间:

这种方案是不是爽得多?没有碎片,能够尽量地全部用完空间,但也存在一些问题。

前面那种内存分配方式,虽然容易出现碎片,并且内存空间的利用率低,但是使用性能高,程序能直接从内存信息表获取内存地址,接着就可以直接按照地址来使用内存空间了。

但下面这种分页的方式,程序需要记录的是内存页ID,每次使用时,需要从内存页ID翻译成实际内存地址,多了一次转换。而且这种模式,会浪费一些内存,比如上面申请3个内存空间,实际分配了2个页面共4个内存空间,浪费了1个内存空间。

以上就是基本原理,实际系统中会做非常多的优化。目前各种主流操作系统都是分页的方式,因此你不需要太关心碎片。

四、悟纤小结

师傅:徒儿,不错,不错,探索的不错。总结下今天学习到的知识吧。

悟纤:徒儿这就总结一下。

总结:

(1)内存存储区:动态、静态、程序。
(2)动态存储区:运行阶段可分配的存储空间。
(3)静态存储区:编译阶段就分配好的存储空间。
(4)程序存储区:存放程序语句的存储空间。
(5)内存泄露:没有释放动态分配的内存区域就会造成内存泄露。
(6)内存溢出:程序申请的内存空间大于系统可申请的内存空间就会造成内存溢出。
(7)内存碎片:无法将内存分配给进程(外部碎片)以及分配出去的却不能被使用的空间(内部碎片)。
(8)内存管理方式:标记分配管理(容易产生内存碎片)和基于页面的内存管理(通过浪费内存空间来减少内存碎片)。

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à学院中有Spring Boot相关的课程:
à悟空学院:https://t.cn/Rg3fKJD
SpringBoot视频:http://t.cn/A6ZagYTi
Spring Cloud视频:http://t.cn/A6ZagxSR
SpringBoot Shiro视频:http://t.cn/A6Zag7IV
SpringBoot交流平台:https://t.cn/R3QDhU0
SpringData和JPA视频:http://t.cn/A6Zad1OH
SpringSecurity5.0视频:http://t.cn/A6ZadMBe
Sharding-JDBC分库分表实战:http://t.cn/A6ZarrqS
分布式事务解决方案「手写代码」:http://t.cn/A6ZaBnIr

内存泄漏的原因及解决办法_探索内存碎片化 - 第288篇相关推荐

  1. 内存泄漏的原因及解决办法_浅谈 JS 内存泄漏问题

    什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高 ...

  2. 内存泄漏的原因及解决办法_编程基础 | C++片段 指针、多态和内存分配

    本片段将介绍运行期而不是编译期的内存分配 1.变量的内存分配和方法的前期绑定 函数中声明的局部变量与其参数以及簿记数据一起被放置在一个活动记录中.活动记录存储在名为运行期栈(run-time stac ...

  3. 内存泄漏的原因及解决办法_内存泄漏的场景和解决办法

    1.非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,就会长期的维持着外部类的引用,组织被系统回收,解决办法是使用静态内部类 2.多线程相关的匿名内部类和非静态内部类 匿名内部类同样会持 ...

  4. 什么是内存泄漏,常见引起引起内存泄漏的原因,及解决办法

    一:什么是内存泄露 内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存 ...

  5. 多线程内存泄漏_内存泄漏的场景和解决办法

    1.非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,就会长期的维持着外部类的引用,组织被系统回收,解决办法是使用静态内部类 2.多线程相关的匿名内部类和非静态内部类 匿名内部类同样会持 ...

  6. 内存泄漏的原因及解决方法

    内存泄漏就是内存中的变量没有回收,一直存在与内存中,造成内存的浪费的行为.常见的内存泄漏有以下5种 1. 意外的全局变量 2. 计时器和回调函数timers 3. DOM泄漏 4. js闭包 5. c ...

  7. java面试-内存溢出的原因及解决办法

    内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存. 引起内存溢出的原因有很多种,常见的有以下几种: 1.内存中加载的数据量过于庞大,如一 ...

  8. iOS 检测内存泄漏Analyze的一些解决办法

    开发过程中管理好内存至关重要.xcode5出来之后已经开始arc自动管理内存,在一定程度上避免了一些内存的管理.但还是多少会遇到棘手的问题. XCode的Analyze能分析到内存泄露的地方,快捷键s ...

  9. redis 删除数据,但是占用内存没有下降原因及解决办法

    在使用 Redis 时,我们经常会遇到这样一个问题:明明做了数据删除,数据量已经不大了,为什么使用 top 命令查看时,还会发现 Redis 占用了很多内存呢? 实际上,这是因为,当数据删除后,Red ...

最新文章

  1. im和音视频开发哪个更好_找时间成为更好的开发人员
  2. 基于TCP的应用层协议、与基于UDP的应用层协议分别有哪些?
  3. 综述丨七场高端报告,带你大视角看人工智能发展
  4. java递归整数逆序,将一个整数逆序输出,分别给出递归和非递归算法 | 学步园...
  5. DialogFragment 将数据传回Activity的onActivityResult方法
  6. bazel 链接第三方动态库_如何自己制作静态库?
  7. java servlet init方法_Java HttpServlet.init方法代码示例
  8. HTML5程序开发范例宝典(韩旭著)读书笔记之渐变背景
  9. 实例:评审速度与缺陷密度之间的相关性
  10. AI和大数据结合,智能运维平台助力流利说提升竞争力
  11. 解析常见网络钓鱼攻击方法
  12. table宽度一样宽_table自适应宽度
  13. windows下之定时执行bat脚本
  14. 构建“未来级”企业,如何做对这道必答题
  15. JPA 关联表添加关联条件@Where、@WhereJoinTable()
  16. 奥巴马获胜的秘密武器--“长尾效应”
  17. 华为交换机设置端口聚合的方法
  18. java程序设计答案电子工业出版社_java 语言程序设计(机械工业出版社)课后习题答案 - 下载 - 搜珍网...
  19. python 高斯金字塔_Python OpenCV 之图像金字塔,高斯金字塔与拉普拉斯金字塔
  20. Java使用多线程和GUI实现购买火车票<集合>

热门文章

  1. java.io.NotSerializableException: com.codahale.metrics.MetricRegistry
  2. Greenplum分区
  3. Spark中RDD与DataFrame与DataSet的区别与联系
  4. Spring Boot 操作 Memcache
  5. 存储维护和服务器的区别,存储服务器和普通服务器区别是什么? 你想知道吗服务器类型一般是什么...
  6. 学了Java就有用,是本世纪最大的谎言
  7. linux 实验指导书,linux操作系统实验指导书新 - 图文
  8. 关于json包爆红我有话说
  9. Solr 新增、更新、删除索引
  10. day22,ConfigParser,subprocess,xlrd三个模块