第一节 内存管理

第一节 内存管理

文章内容输出来源:拉勾教育Java高薪训练营

1.为什么需要内存管理

随着硬件技术不断发展,高级编程语言中都自带了GC垃圾回收机制,这些变化,让我们不需要注意内存空间使用的情况下,也能去完成各种功能开发

  • 如下代码从语法角度上没有任何问题
  • 但是从内存管理上纯在内存泄漏
  • 用Performance查看js Heap会发现蓝色线条持续升高,没有回落

    console.log('内存管理');
    function fn() {
      arrList = []
      arrList[100000] = 'lg is codere'
    }
    fn()

2. 基本介绍

  • 内存: 由可读写单元组成,表示一片可操作空间
  • 人为去操作一片空间的申请,使用和释放
  • 内存管理: 开发者主动申请空间,使用空间,释放空间
  • 管理流程: 申请-使用-释放

3. javascript中的内存管理

// 申请
let obj = {}

// 使用
obj.name = "hello"

// 释放
obj = null

4. javascirpt中的垃圾

  • javascritp 中的内存管理是自动的

每当我们创建一个对象或者数组等的时候,js引擎都会自动分配内存空间,
后续代码在执行的过程中无法,通过引用关系,无法找到对象的时候,就会被GC自动回收

  • 对象不再被引用是垃圾
  • 对象不能从根上访问到时是垃圾

4.1 可达对象

  • 可以被访问到的对象就是可达对象(引用,作用域链)
  • 可达的标准就是从根出发是否能被找到
  • javascript中的根就是可以理解为全局变量对象

4.2 javascript 中的引用和可达表现

  1. 例子1
  • 对象{name: ‘test’}被obj引用
  • 然后把{name: ‘test’}这个对象的引用赋值给other
  • 把obj设置为null
  • 虽然obj为null了,但是{name: ‘test’}对象的引用还有other
  • 所以{name: ‘test’} 这个对象是可达的
let obj = {name: 'test'}

let other = obj

obj = null

  1. 例子2 循环引用

所有对象都可以从根上查找
image.png

function createObj(obj1,obj2) {
  obj1.next = obj2
  obj2.prev = obj1
  return {
    o1: obj1,
    o2: obj2
  }
}

let obj = createObj({name: 'obj1'},{name: 'obj2'})
console.log(obj);

5. GC算法

  • GC是垃圾回收机制的简写
  • GC可以找到内存中的垃圾,并释放和回收空间
  • GC里的垃圾是什么
    • 程序中不在使用的对象
function func() {
  const name = 'lg'
  return `${name} is a code`
}
func()

  • GC是一种机制,垃圾回去器完成具体的工作
  • 工作的内容就是查找垃圾释放空间,回收空间
  • 算法就是工作时查找和回收所遵循的规则
    • 引用计数

通过对对象的引用计数,判断当前对象是否是垃圾

  • 标记清除
    • 给活动对象添加一个标记,来判断是否是垃圾
  • 标记整理
    • 碎片化整理
  • 分代回收
    • v8 根据对象的情况分新生代和老龄代,并有不同的回收机制

5.1 引用计数

5.1.1 思想
  • 核心思想: 设置当前对象的引用数,判断当前引用数是否为0
  • 引用计数器
    • 引用关系改变时,引用计数器主动修改引用数字
  • 当引用数为0时,GC开始进行回收工作,并释放空间

当脚本执行完之后
user1/user2/user3因为在全局有ageList引用,所以不会被回收
fn中的num1/num2执行完之后,没有谁引用 他们,所以会被GC回收

const user1 = {age: 11}
const user2 = {age: 12}
const user3 = {age: 13}

const ageList = [user1.age,user2.age,user3.age]

function fn() {
  const num1 =1
  const num2 =2
}
fn()

5.1.2 优缺点

优点

  • 发现垃圾时立即回收
    • 当引用数为0时,GC立即开始进行回收工作,并释放空间
  • 最大限度减少程序的暂停
    • 应用程序执行的过程中必定会对内存进行消耗,当前的平台内存有上限,如果及时回收内存,可以防止内存沾满的时候

缺点

  • 无法回收循环引用的对象

如下,虽然方法执行完了,但是obj1和obj2的names属性互相引用对方,所以引用计数的数值并不是为0
所以GC并没有回收它们,造成了空间的浪费

function fn() {
  const obj1 = {}
  const obj2 = {}
  obj1.name = obj2
  obj2.name = obj1

  return 'test'
}
fn()

  • 时间开销大
    • 要时刻监控着对象引用数值的变化,如果多个对象需要修改,那么需要的时间就会大一点

5.2 标记清除

5.2.1 思想
  • 核心思想: 分标记和清除2个阶段完成
  • 遍历所有对象,找到活动对象,然后进行标记操作
  • 遍历所有对象,把没有标记的对象进行清除,然后把第一阶段中的对象的标记进行抹除
  • 相当于两次遍历把不可达对象就行清除,然后回收空间

有三个全局对象A,B,C,然后在是在每个对象中又递归寻找可达对象,进行标记
如果在某个函数中有a1和b1两个对象,执行完之后,从全局变量出发,没有找到引用的标记
那么这2个对象就会被GC清除,
同时会把清除的空间放到空闲列表中,方便后续程序申请空间使用
image.png

5.2.2 优缺点

优点
可以解决循环引用,没有被GC回收的问题
缺点
例如在根下有一个引用的可达对象,也就是红色区域
红色区域左右 两侧的对象,是不可达对象,所以被GC回收,并且空间被添加空闲链表中
后续的程序可以从空闲链表中申请相应大小的空间
问题就来了
一般存储信息分头和域两部分
头是存储数据的元信息
域是存储具体数据的,
虽然空闲链表中有三个域,但是被红色区域分隔开来,地址不连续
如果程序申请的空间大于1个域小于2个域,那么就会出现空间碎片化的问题
空间碎片化
使用标签清除算法之后,回收的空间,在下次程序申请的时候出现,空间大小不匹配的情况,要么出现空间多余,要么出现空间不够
所以就会出现内存空间不能够最大化的使用
image.png
标记清除需要遍历2次才能够进行回收,所以不会马上进行回收垃圾,

5.3 标记整理

5.3.1 思想
  • 标记整理可以看做是标记清除的增强
  • 标记阶段的操作和标记清除一致
  • 清除阶段胡先整理,移动对象位置,使空闲空间地址上你能够产生连续
  • image.png
  • 整理后会把非活动对象和空闲空间进行整理,让地址连续,然后对内存右侧的空间进行整体回收
  • image.png
  • image.png

这样整理后就不会出现大批量的小空间,后续我们程序申请内存的时候就可以,最大化利用内存空间

5.3.2 优缺点

优点
减少碎片化空间
缺点
不会立即回收垃圾对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值