You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FileOutputStream写入文件时遭遇偶发OutOfMemoryError求助

问题分析与解决方案

核心问题

  1. 递归死循环触发OOM:写入文件抛出IOException时,catch块调用debug(),而debug()又会触发writeFile(),形成无限递归。每次递归都会生成新的字符串、字节数组,持续消耗内存直到触发OutOfMemoryError。
  2. 内存开销累积:每次写入都通过formatLog()生成字符串再转ByteArray,频繁的对象创建在循环中会快速耗尽可用内存。

具体修复步骤

1. 打破递归死循环

修改writeFile的异常捕获逻辑,禁止在catch块中调用会触发写入的debug(),改用Logcat输出错误:

private fun writeFile(tag: String, msg: String, exception: Throwable?) {
    try {
        logFileOutputStream?.let { outputStream ->
            outputStream.write(formatLog(msg).toByteArray())
            outputStream.flush()
        }
    } catch (e: IOException) {
        // 改用Logcat输出,避免触发递归写入
        android.util.Log.e(TAG, "写入日志失败: $msg, 错误信息: ${e.message}")
    }
}

2. 优化内存使用

用BufferedWriter包装输出流,直接写入字符串,避免频繁的String转ByteArray操作,减少内存开销:

// 初始化时替换FileOutputStream为BufferedWriter
private var logWriter: BufferedWriter? = null

// 初始化示例
fun initLogFile(file: File) {
    try {
        logWriter = BufferedWriter(FileWriter(file, true))
    } catch (e: IOException) {
        android.util.Log.e(TAG, "初始化日志文件失败: ${e.message}")
    }
}

private fun writeFile(tag: String, msg: String, exception: Throwable?) {
    try {
        logWriter?.let { writer ->
            writer.write(formatLog(msg))
            writer.flush()
        }
    } catch (e: IOException) {
        android.util.Log.e(TAG, "写入日志失败: $msg, 错误信息: ${e.message}")
    }
}

private fun formatLog(msg: String): String {
    val dateTime = DateFormatterUtility.formatDateTimeToString(Date(), "MM/dd/yyyy HH:mm:ss.SSS")
    return "$dateTime : $msg\n"
}

3. 额外防护措施

  • 写入前检查日志文件状态:确认文件存在、可写,以及剩余磁盘空间充足。
  • 限制单条日志长度:对超大内容的日志进行拆分或截断,避免一次性占用过多内存。
  • 增加OOM异常捕获作为最后防线:
private fun writeFile(tag: String, msg: String, exception: Throwable?) {
    try {
        logWriter?.let { writer ->
            writer.write(formatLog(msg))
            writer.flush()
        }
    } catch (e: IOException) {
        android.util.Log.e(TAG, "写入日志失败: $msg, 错误信息: ${e.message}")
    } catch (e: OutOfMemoryError) {
        android.util.Log.e(TAG, "内存不足,无法写入日志")
        // 可考虑释放部分资源或暂时停止日志写入
    }
}

内容的提问来源于stack exchange,提问作者Anshul Tyagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:15:30