尝试在手机内存上写时出现致命异常:java.lang.OutOfMemoryError

时间:2017-12-26 16:15:07

标签: java android out-of-memory

这是一个完整的例外:

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 79386366 byte allocation with 16777216 free bytes and 75MB until OOM
   at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
   at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:133)
   at java.lang.StringBuilder.append(StringBuilder.java:124)
   at ch.usi.jacopofidacaro.umob.background.RecordStorageManager.store(RecordStorageManager.java:156)
   at ch.usi.jacopofidacaro.umob.recordCommuter.RecordCommuter.storeLocally(RecordCommuter.java:76)
   at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder.recordGyroscope(BackgroundRecorder.java:591)
   at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder$1.run(BackgroundRecorder.java:139)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:148)
   at android.app.ActivityThread.main(ActivityThread.java:5417)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

这就是发生的地方:

public void store(Record record, String recordId, Context ctx, String recordType) {

    Log.i(STORE, "store():");

    // convert the POJO to JSON
    Gson gson = new Gson();
    String json = gson.toJson(record);

    String filePath = recordType + "_records";
    File file = new File(ctx.getFilesDir(), filePath);
    Log.i(STORE, "  target file: " + file.getAbsolutePath());


    Log.i(STORE, "  locally storing record: " + recordId);
    try {

        if (!file.exists()) file.createNewFile();
        FileWriter fw = new FileWriter(file.getAbsolutePath(), true);
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(json);
        bw.close();

        FileReader fr = new FileReader(file.getAbsolutePath());
        BufferedReader br = new BufferedReader(fr);
        StringBuilder text = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null)
            text.append(line).append('\n');
        br.close();
        Log.i(STORE, "  record stored.");


    } catch (Exception e) {

        e.printStackTrace();

    }

}

简而言之,我正在读取陀螺仪传感器数据并将其存储在名为gyroscope_records的本地文件中。每小时,我都会连接到Firebase上传文件并开始写入下一个小时的新文件。在我看来,如果传感器读数太多而文件变得非常大,那么就会发生这种异常。但是,我不知道如何处理它。如何读取/写入大文件(如果这是问题)?

2 个答案:

答案 0 :(得分:0)

不知何故,您必须将文件分解为更小的部分。你目前有一个近80MB的文件,听起来它可能变得更大。您的问题是,您正试图将整个文件读入内存,而且您无法做到。

一些建议:

  • 创建许多小文件。我不知道Record在这种情况下有多大,但可能每分钟都有一个新文件或者记录数量较少的东西。
  • 使用SQLite并将每条记录存储在数据库中。定期让另一个线程读出这些记录,发送它们并删除它们。
  • 仅附加到大文件。不要把它读入内存。

还有其他可能性,但你根本无法将其全部留在记忆中。

答案 1 :(得分:0)

我认为在StringBuilder“text”中没有用,但导致异常的是text.append(...)。那么您是否尝试将变量与while循环一起删除?