searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

内存泄漏导致程序闪退解析

2024-08-07 09:34:11
14
0
内存泄漏是指程序在运行过程中动态分配的内存由于某种原因无法被释放,从而导致系统中的可用内存不断减少,最终可能导致程序性能下降甚至闪退。

最常见事件监听器正确移除长期持有使用大对象数据。

事件监听器未正确移除:

场景在小程序中添加了事件监听器(例如页面监听器、定时器、网络请求等),但在页面卸载或组件销毁时未正确移除,导致监听器仍然存在,从而无法被垃圾回收器释放。

示例代码

Page({
  onLoad() {
    this.timer = setInterval(() => {
      console.log('Interval callback');
    }, 1000);
  },
  onUnload() {
    clearInterval(this.timer); // 在页面卸载时清除定时器
  }
});
 

页面Page)中定时器如果页面onUnload函数没有清除定时器这些定时器将会继续持有页面对象引用可能导致页面卸载仍然无法完全释放直到定时器函数执行完毕手动清除

组件(Component)中定时器同理

长期持有未使用的大对象或数据:

场景: 当页面或组件持有大量的数据或对象(例如:长列表不断下拉),而这些数据在后续的操作中不再被使用,但由于被持有而无法被释放。

示例

// 持有大量数据的例子
Page({
  data: {
    largeData: [], // 假设这是一个很大的数据数组
  },
  onLoad() {
    // 加载大量数据到页面中
    this.setData({
      largeData: Array.from({ length: 10000 }, (_, index) => `Item ${index + 1}`),
    });
  },
  onUnload() {
    // 在页面卸载时,如果不再需要 largeData,应该置空释放内存
    this.setData({
      largeData: [],
    });
  }
});
 

循环引用导致的对象无法释放:

场景: 当两个对象互相引用,且存在至少一个对象被全局变量或闭包所引用时,这种循环引用会导致对象无法被垃圾回收,从而引发内存泄漏。

示例

// 循环引用示例
let obj1 = {};
let obj2 = {};

obj1.ref = obj2;
obj2.ref = obj1;

// 确保在不再需要时解除引用
obj1 = null;
obj2 = null;
 

频繁创建和销毁组件实例:

场景: 当页面频繁创建和销毁组件实例,而未能正确释放之前组件实例所占用的资源。

示例

// 频繁创建和销毁组件示例
Page({
  onTapCreateComponent() {
    const componentInstance = this.selectComponent('#my-component');
    if (!componentInstance) {
      const newComponentInstance = this.selectComponent('#my-component');
      // 如果频繁创建实例,应该在不再需要时及时销毁
      newComponentInstance.destroy(); // 假设 destroy 方法用于销毁组件
    }
  }
});
 

存在内存泄漏用户长期使用导致小程序占用内存越来越最后导致小程序闪退(被微信强制销毁)

可以用weakSet排查页面泄漏问题

weakSet是JavaScript一种数据结构可以存储对象并且存储的对象弱引用一个对象只被weakSet引用后会被垃圾回收回收

可以通过打印weakSet指向知道里面元素是否垃圾回收器回收

示例

1.创建weakSet对象用来存储需要监控对象

// 在页面或组件的数据部分定义一个 WeakSet 对象
let monitoredObjects = new WeakSet();
 

2.添加需要监控对象需要进行监控地方(例如页面加载时)需要监控对象添加weakSet

// 示例:在 onLoad 生命周期函数中添加需要监控的对象
onLoad() {
    let obj = {}; // 假设这是需要监控的对象
    monitoredObjects.add(obj);
    // 其他初始化操作
}
 

3.检查页面卸载情况页面卸载(例如onUnload生命周期)检查weakSet对象是否释放

// 示例:在 onUnload 生命周期函数中检查被监控对象的状态
onUnload() {
    for (let obj of monitoredObjects) {
        // 可以输出或者记录被监控对象的状态,用于排查问题
        console.log('Monitored object:', obj);
    }
    // 清空 WeakSet 对象,准备下次使用
    monitoredObjects = new WeakSet();
}
 

也可以微信开发工具其他性能分析工具监控优化应用内存使用情况及时发现解决潜在内存泄漏问题

0条评论
0 / 1000
w****n
17文章数
1粉丝数
w****n
17 文章 | 1 粉丝
原创

内存泄漏导致程序闪退解析

2024-08-07 09:34:11
14
0
内存泄漏是指程序在运行过程中动态分配的内存由于某种原因无法被释放,从而导致系统中的可用内存不断减少,最终可能导致程序性能下降甚至闪退。

最常见事件监听器正确移除长期持有使用大对象数据。

事件监听器未正确移除:

场景在小程序中添加了事件监听器(例如页面监听器、定时器、网络请求等),但在页面卸载或组件销毁时未正确移除,导致监听器仍然存在,从而无法被垃圾回收器释放。

示例代码

Page({
  onLoad() {
    this.timer = setInterval(() => {
      console.log('Interval callback');
    }, 1000);
  },
  onUnload() {
    clearInterval(this.timer); // 在页面卸载时清除定时器
  }
});
 

页面Page)中定时器如果页面onUnload函数没有清除定时器这些定时器将会继续持有页面对象引用可能导致页面卸载仍然无法完全释放直到定时器函数执行完毕手动清除

组件(Component)中定时器同理

长期持有未使用的大对象或数据:

场景: 当页面或组件持有大量的数据或对象(例如:长列表不断下拉),而这些数据在后续的操作中不再被使用,但由于被持有而无法被释放。

示例

// 持有大量数据的例子
Page({
  data: {
    largeData: [], // 假设这是一个很大的数据数组
  },
  onLoad() {
    // 加载大量数据到页面中
    this.setData({
      largeData: Array.from({ length: 10000 }, (_, index) => `Item ${index + 1}`),
    });
  },
  onUnload() {
    // 在页面卸载时,如果不再需要 largeData,应该置空释放内存
    this.setData({
      largeData: [],
    });
  }
});
 

循环引用导致的对象无法释放:

场景: 当两个对象互相引用,且存在至少一个对象被全局变量或闭包所引用时,这种循环引用会导致对象无法被垃圾回收,从而引发内存泄漏。

示例

// 循环引用示例
let obj1 = {};
let obj2 = {};

obj1.ref = obj2;
obj2.ref = obj1;

// 确保在不再需要时解除引用
obj1 = null;
obj2 = null;
 

频繁创建和销毁组件实例:

场景: 当页面频繁创建和销毁组件实例,而未能正确释放之前组件实例所占用的资源。

示例

// 频繁创建和销毁组件示例
Page({
  onTapCreateComponent() {
    const componentInstance = this.selectComponent('#my-component');
    if (!componentInstance) {
      const newComponentInstance = this.selectComponent('#my-component');
      // 如果频繁创建实例,应该在不再需要时及时销毁
      newComponentInstance.destroy(); // 假设 destroy 方法用于销毁组件
    }
  }
});
 

存在内存泄漏用户长期使用导致小程序占用内存越来越最后导致小程序闪退(被微信强制销毁)

可以用weakSet排查页面泄漏问题

weakSet是JavaScript一种数据结构可以存储对象并且存储的对象弱引用一个对象只被weakSet引用后会被垃圾回收回收

可以通过打印weakSet指向知道里面元素是否垃圾回收器回收

示例

1.创建weakSet对象用来存储需要监控对象

// 在页面或组件的数据部分定义一个 WeakSet 对象
let monitoredObjects = new WeakSet();
 

2.添加需要监控对象需要进行监控地方(例如页面加载时)需要监控对象添加weakSet

// 示例:在 onLoad 生命周期函数中添加需要监控的对象
onLoad() {
    let obj = {}; // 假设这是需要监控的对象
    monitoredObjects.add(obj);
    // 其他初始化操作
}
 

3.检查页面卸载情况页面卸载(例如onUnload生命周期)检查weakSet对象是否释放

// 示例:在 onUnload 生命周期函数中检查被监控对象的状态
onUnload() {
    for (let obj of monitoredObjects) {
        // 可以输出或者记录被监控对象的状态,用于排查问题
        console.log('Monitored object:', obj);
    }
    // 清空 WeakSet 对象,准备下次使用
    monitoredObjects = new WeakSet();
}
 

也可以微信开发工具其他性能分析工具监控优化应用内存使用情况及时发现解决潜在内存泄漏问题

文章来自个人专栏
Vue前端开发
17 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0