内存分配问题修复说明.md 3.9 KB

UpdateHelper 内存分配问题修复说明

问题描述

在安装大文件(约 249 MB)时,UpdateHelper 安装器出现内存分配失败错误:

Failed to allocate 261074082 because only 184929076 allocatable

错误含义:

  • 尝试分配:261,074,082 字节(约 249 MB)
  • 可用内存:184,929,076 字节(约 176 MB)
  • 问题:可用堆内存不足,无法满足分配需求

问题原因分析

  1. UpdateHelper 未启用大堆内存

    • 主应用(HeartRate)在 AndroidManifest.xml 中已配置 android:largeHeap="true"
    • UpdateHelper 应用未配置此属性,导致默认堆内存较小(通常为 48-192 MB,取决于设备)
    • 当处理大文件(>200 MB)时,堆内存不足
  2. 内存使用优化不足

    • 虽然使用了流式读取(64KB 缓冲区),但在处理大文件时仍可能出现内存峰值
    • 缺少显式的内存管理和错误处理

修复方案

1. 启用大堆内存(主要修复)

UpdateHelper/src/main/AndroidManifest.xml 中添加:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"  <!-- 新增:启用大堆内存 -->
    android:theme="@style/Theme.UpdateHelper">

效果:

  • 启用后,应用可使用的堆内存从默认值(通常 48-192 MB)增加到 512 MB 或更多(取决于设备)
  • 足以处理 250+ MB 的 APK 文件

2. 优化内存使用(辅助优化)

MainActivity.javaperformInstall() 方法中:

a) 减小缓冲区大小

  • 修改前:64KB 缓冲区
  • 修改后:32KB 缓冲区
  • 原因:减小峰值内存使用,同时保持合理的性能

b) 添加内存管理

  • 在处理大文件(>100 MB)前,建议系统进行垃圾回收
  • 在文件流关闭后,再次建议垃圾回收
  • 显式关闭文件流,确保及时释放资源

c) 增强错误处理

  • 专门捕获 OutOfMemoryError,提供更友好的错误提示
  • 确保在异常情况下也能正确关闭流

修复后的代码变更

AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"  <!-- 新增 -->
    android:theme="@style/Theme.UpdateHelper">

MainActivity.java

主要变更:

  1. 缓冲区从 64KB 减小到 32KB
  2. 添加大文件处理前的 GC 建议
  3. 显式关闭文件流
  4. 添加 OutOfMemoryError 专门处理
  5. 改进错误处理和资源清理

验证方法

  1. 重新编译 UpdateHelper

    cd bBeng-HeartRate-4.66-pad
    ./gradlew :UpdateHelper:assembleRelease
    
  2. 安装新的 UpdateHelper APK

    • 将生成的 APK 安装到设备上
  3. 测试大文件安装

    • 从 app-info.vue 页面下载大文件(>200 MB)
    • 使用 UpdateHelper 安装
    • 验证是否不再出现内存分配错误

注意事项

  1. largeHeap 的影响

    • android:largeHeap="true" 会增加应用的内存占用
    • 但 UpdateHelper 是轻量级应用,主要用于安装,影响可接受
    • 系统会根据设备可用内存动态调整实际堆大小
  2. 设备兼容性

    • largeHeap 属性在 Android 3.0+ (API 11+) 支持
    • UpdateHelper 的 minSdkVersion 是 21,完全兼容
  3. 性能考虑

    • 32KB 缓冲区在大多数设备上性能足够
    • 如果设备性能较差,可以进一步减小到 16KB,但会增加 I/O 次数

相关文件

  • UpdateHelper/src/main/AndroidManifest.xml - 添加 largeHeap 配置
  • UpdateHelper/src/main/java/com/yuyetech/updatehelper/MainActivity.java - 优化内存管理

总结

通过启用 largeHeap 和优化内存使用,UpdateHelper 现在可以处理更大的 APK 文件(理论上可处理 500+ MB 的文件,取决于设备可用内存)。修复后,应该能够成功安装 249 MB 的 APK 文件。