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

Android解压1.5GB压缩包仅完成100MB即崩溃,求排查方案

解压大压缩包崩溃的排查与修复方案

核心问题排查点及修复建议

1. 频繁调用publishProgress导致主线程负载过高

当前代码每读取4KB数据就触发一次UI更新,解压100MB数据会产生约25000次进度回调,严重阻塞主线程,引发ANR或内存崩溃。

修复方案:
改为累计读取一定大小(如1MB)或进度变化超过1%时才更新UI,减少主线程压力:

// 将进度累计变量改为long类型,避免溢出
long publishprogress = 0;
long length = entry.getSize();
int lastProgress = -1; // 记录上次更新的进度,避免重复触发
int count;
while ((count = zin.read(buffer)) != -1) {
    out.write(buffer, 0, count);
    publishprogress += count;
    int currentProgress = (int) (publishprogress * 100 / length);
    // 仅当进度发生变化时才更新UI
    if (currentProgress != lastProgress) {
        publishProgress(currentProgress);
        lastProgress = currentProgress;
        System.out.println("DEBUGLOG_19 " + count + "-------publishprogress " + currentProgress + "         "+ entry.getName());
    }
}

2. int类型溢出风险

publishprogress使用int类型,若解压单个接近2GB的文件(int最大值为2^31-1≈2GB),会导致数值溢出,引发进度计算错误或异常。

修复方案:
将publishprogress声明为long类型,与entry.getSize()的long类型匹配,避免溢出。

3. 流资源未安全释放

手动调用close()方法时,若中途抛出异常,流资源可能无法正常关闭,长期运行会导致资源泄漏。

修复方案:
使用Java的try-with-resources语法自动管理流资源,确保资源正常释放:

// 自动管理ZipInputStream
try (ZipInputStream zin = new ZipInputStream(new FileInputStream(file))) {
    ZipEntry entry;
    String name, dir;
    while ((entry = zin.getNextEntry()) != null) {
        name = entry.getName();
        if (entry.isDirectory()) {
            mkdirs(outdir, name);
            continue;
        }
        dir = dirpart(name);
        if (dir != null) {
            mkdirs(outdir, dir);
        }
        byte[] buffer = new byte[4096];
        // 自动管理BufferedOutputStream
        try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(outdir, name)))) {
            long publishprogress = 0;
            long length = entry.getSize();
            int lastProgress = -1;
            int count;
            while ((count = zin.read(buffer)) != -1) {
                out.write(buffer, 0, count);
                publishprogress += count;
                int currentProgress = (int) (publishprogress * 100 / length);
                if (currentProgress != lastProgress) {
                    publishProgress(currentProgress);
                    lastProgress = currentProgress;
                    System.out.println("DEBUGLOG_19 " + count + "-------publishprogress " + currentProgress + "         "+ entry.getName());
                }
            }
            System.out.println("DEBUGLOG_05");
        }
    }
    System.out.println("DEBUGLOG_06");
} catch (IOException e) {
    e.printStackTrace();
    writeLog(e);
}

4. 路径分隔符处理错误

dirpart方法使用File.separator,但Zip包内的路径分隔符固定为/,若设备系统分隔符不同,会导致目录创建失败。

修复方案:
统一使用/分割Zip entry路径:

private String dirpart(String name) {
    int index = name.lastIndexOf("/");
    return index == -1 ? null : name.substring(0, index);
}

5. 解压失败仍删除原压缩包

onPostExecute中无论解压是否成功都会删除压缩包,导致用户无法重试。

修复方案:
仅在解压成功时删除压缩包,通过doInBackground返回状态标识:

@Override
protected String doInBackground(String... params) {
    try {
        // ... 原有解压逻辑
        return "success";
    } catch (IOException e) {
        e.printStackTrace();
        writeLog(e);
        return "fail";
    }
}

@Override
protected void onPostExecute(String result) {
    loading.setVisibility(View.INVISIBLE);
    progressloading.setVisibility(View.INVISIBLE);
    if ("success".equals(result)) {
        com.luxury.launcher.other.Utils.delete(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/game.zip"));
        StartGame();
    } else {
        // 可添加解压失败的提示逻辑
    }
}

6. 额外排查项

  • 磁盘空间检查:解压前确认目标目录可用空间是否足够(1.5GB压缩包解压后通常更大,建议预留2倍以上空间):
File outdir = new File(destinationPath);
long freeSpace = outdir.getFreeSpace();
long requiredSpace = new File(filePath).length() * 2;
if (freeSpace < requiredSpace) {
    // 提示用户磁盘空间不足
    return "no_space";
}
  • AsyncTask局限性:长时间解压任务建议改用Coroutine或WorkManager,避免系统因进程优先级回收导致任务中断。

内容的提问来源于stack exchange,提问作者Максим Белый

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:45:08