Android逆シーケンス化異常EOFExceptionの解決


プロジェクトの中でずっとシーケンス化の方式でいくつかのキャッシュを配置して、今日魅族MX 5の上で反シーケンス化のキャッシュの内容が失効したことを発見して、間違いを報告します
java.io.EOFException     at java.io.DataInputStream.readByte(DataInputStream.java:77)     at java.io.ObjectInputStream.nextTC(ObjectInputStream.java:505)     at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:752)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)     at java.io.ObjectInputStream.readFieldValues(ObjectInputStream.java:1113)     at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:454)     at java.io.ObjectInputStream.readObjectForClass(ObjectInputStream.java:1345)     at java.io.ObjectInputStream.readHierarchy(ObjectInputStream.java:1242)     at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1835)     at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)     at java.util.ArrayList.readObject(ArrayList.java:661)     at java.lang.reflect.Method.invoke(Native Method)     at java.lang.reflect.Method.invoke(Method.java:372)     at java.io.ObjectInputStream.readObjectForClass(ObjectInputStream.java:1330)     at java.io.ObjectInputStream.readHierarchy(ObjectInputStream.java:1242)     at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1835)     at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)     at com.imaginato.qravedconsumer.handler.bv.a(Unknown Source)     at com.imaginato.qravedconsumer.handler.bv.a(Unknown Source)     at com.imaginato.qravedconsumer.fragment.bl.a(Unknown Source)     at com.imaginato.qravedconsumer.fragment.bl.doInBackground(Unknown Source)     at android.os.AsyncTask$2.call(AsyncTask.java:292)     at java.util.concurrent.FutureTask.run(FutureTask.java:237)     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)     at java.lang.Thread.run(Thread.java:818)
シーケンス化されたコードは次のとおりです.
 /**
     *       list
     * @param context
     * @param fileName
     * @param <T>
     * @return
     * @author Alex
     */
    public <T> List<T> getArrayListFromDisk(Context context, String fileName) {
        if (context == null) return null;
        ObjectInputStream ois = null;
        File file = context.getCacheDir();
        String path = file.getAbsolutePath().concat(fileName);
        File target = new File(path);
        if (!target.exists()) {
            Log.i("Alex","      "+fileName);
            return null;
        }
        List<T> arrayList = null;
        synchronized (ArrayListLock) {
            try {
                ois = new ObjectInputStream(new FileInputStream(target));
                arrayList = (ArrayList<T>) ois.readObject();
                return arrayList;
            } catch (ClassNotFoundException e) {
                Log.i("Alex", "     ", e);
            } catch (IOException e) {
                Log.i("Alex", "     2", e);//            
            } finally {
                if (ois == null) return null;
                try {
                    ois.close();
                } catch (IOException e) {
                    Log.i("Alex", "     3", e);
                }
                return arrayList;
            }
        }
    }

最初は、同じファイルに対してリード・スレッドとライト・スレッドが同時にストリームを確立したことによるエラーだと思っていましたが、リード・ライト・メソッドにスレッド・ロックをかけました.その後、役に立たず、リード・ライト・スレッドの時間間隔が大きく、同期はほとんど発生しません.
タスクマネージャを使用してappを強制的に閉じる場合によく発生します.
その後、シーケンス化されたファイルの破損による可能性があることが判明し、1つのスレッドでこのファイルに対して書き込み操作を実行し、スレッドが正常に終了せずに強制的に終了した場合、現在の操作のファイルが破損する可能性があるため、問題のあるコードは次の通りです.
@Override
    public void onDestroy() {
        Log.i("Alex", "fragment2 onStop  ");
        if (aveArrayListToDisk(getActivity(), CARDS_LIST, "/homeCards.tmp"))
            JLogUtils.i("Alex", "          ");
        else Log.i("Alex", "       ");
        super.onDestroy();
        Log.i("Alex", "fragment onDestroy   !!!");
    }

これはFragmentのonDestroy()メソッドで、その中で「fragmentのonDestroyが実行しました!!」印刷されません.解決方法は簡単で、このIOコードをonStop()に書けばいいです.
このバグで得られた教訓は,時間をかけて操作をonDestroy()に入れないことであり,onDestroy()は実行されないか,appを実行したプロセスが終了するのを待っていない可能性があり,これはIO操作に致命的である.