1. 程式人生 > >Android 反序列化異常EOFException的解決

Android 反序列化異常EOFException的解決

專案裡之前一直用序列化的方式部署一些快取,今天在魅族MX5上發現反序列化快取內容失效了,報錯內容如下

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的時候經常會出現這種情況

後來發現可能是由於序列化檔案損壞引起的,如果在一個執行緒裡對這個檔案執行寫入操作,而執行緒沒有正常的結束而被強行終止了,可能會導致當前操作的檔案損壞,所以導致問題的程式碼如下

@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()裡去就可以了。

這個bug得到的教訓是,耗時操作不要放在onDestroy()裡,onDestroy()可能不會被執行或者還沒等執行完app的程序就被終止了,這對IO操作是致命的。

相關推薦

Android 序列異常EOFException解決

專案裡之前一直用序列化的方式部署一些快取,今天在魅族MX5上發現反序列化快取內容失效了,報錯內容如下 java.io.EOFException     at java.io.DataInputStream.readByte(DataInputStream.java:77)

unserialize序列錯誤的解決辦法

replace 序列 lac pre col 反序 blog 解決辦法 repl 1. UTF-8編碼解決反序列化出錯問題 function mb_unserialize($serial_str) { $serial_str = str_replace("\r",

php 序列返回false解決方法

反序 blog $2 序列化 nbsp post 序列 php replace function mb_unserialize($serial_str) { $serial_str= preg_replace(‘!s:(\d+):"(.*?)";

處理範例程式碼Webapi中的Monogodb的Bson中ObjectId序列異常

微軟程式碼範例中的一個Bug 處理Monogodb的Bson中ObjectId反序列化異常 Dotnet core 2.1已推出有一段時間,asp.net提供了一段關於Webapi的範例,是使用Dotnet Core+Monogodb搭建Webapi,範例說可以完成Monogodb資料CRUD操作。 一切順

redis序列異常:org.springframework.data.redis.serializer.SerializationException

1、日誌如下 org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer

fastJson序列異常,JSONException: expect ':' at 0, actual =

com.alibaba.fastjson.JSONException: expect ':' at 0, actual = at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:29

spring boot jackon序列異常

1.Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token; 檢測到該欄位是string,而反序列化結果應該是list 2.Illegal unquoted

Redis | 使用redis儲存物件序列異常SerializationFailedException

案例 使用Redis進行物件儲存,在處理業務邏輯的時候,叢Redis獲取物件發現反序列化失敗,丟擲如下異常: Caused by: org.springframework.data.redis.serializer.SerializationExcept

hibernate實體類序列異常

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is o

springboot2.x使用redis作為快取(使用fastjson序列的方式,並除錯序列異常

1.redis是記憶體資料庫,可以單獨作為資料庫(有持久化方案),也可以作為快取(一般為MySQL搭配)        1.1 可以通過jedis,程式碼的方式手動將其傳入redis作為快取;        1.2 也可以通過註解的方式,和spring boo

Java序列時報異常java.io.EOFException

問題 第一種解決辦法 在寫完物件後,加一句 oos.writeObject(null); 插入null是用來判斷是否讀取到結尾。oos是ObjectOutputStream例項。 然後讀物件的時候,使用while ((obj = o

python3 中的Json序列序列 和 字符編碼的問題解決

ron bsp port imp 入參 oos elf asc 反序列化 python3在通過Json往文件裏寫內容時中文字符被轉成unicode編碼 import json class file_open(object): f = open(‘c

WPF序列,傳遞到python序列,報異常

WPF序列化,傳遞到python反序列化,報異常: WPF json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes 說是要用雙引號來將key值括起來 嘗試: 1.在WPF除錯過程中得到

spring+redis 實現快取 解決序列序列的問題

1.config.properties # Redis settings redis.host=127.0.0.1 redis.port=6379   #redis.pass=password redis.dbIndex=0   redis.expiration=3000 &

Hessian2ObjectInput.readObject : hessian 序列空指標異常

java.lang.NullPointerException at sun.reflect.GeneratedConstructorAccessor329.newInstance(Unknown Source) at sun.reflect.DelegatingConst

格式化程式嘗試對訊息序列時引發異常: 嘗試對引數 http://tempuri.org/ 進行序列時出錯: GetLzdtArticleResult。InnerException 訊息是“

當遇到這個錯誤的時候鬱悶了好長時間報錯是字串長度過大可是修改了MaxStringContentLength”屬性的值卻不起作用最後才發現還是因為配置檔案配置的問題在服務端 格式化程式嘗試對訊息反序列化時引發異常: 嘗試對引數 http://tempuri.org/ 進行反

Redis:序列出錯原因以及簡單解決方案

假如專案之間是通過RPC遠端呼叫的,那麼必然會涉及到序列化與反序列化 通常序列化的通用方案都是去繼承一個實現了Serializable 介面的一個基類,比如下圖: 然後讓其他的Domain類去繼承該基類即可: 假如:對應的資料要寫到Redis中,則: //更新Red

解決使用Redis 配置替換fastjson 序列報錯 com.alibaba.fastjson.JSONException: autoType is not support

這幾天用tomcat、nginx、redis配置socket的負載均衡在做資訊共享的使用fastjson反序列化遇到了個啃爹的事情 com.alibaba.fastjson.JSONException: autoType is not support 網上查了下這個錯誤的

android java.io.NotSerializableException序列異常

今天被這個異常坑了好幾個小時。首先把我的需求說下。。今天要開發一個底部Tabbar。但是Tabbar的資料和數量都是在服務端傳過來,然後我們在通過資料繪製Tabbar, 繪製完後需要把這段資訊儲存序列化儲存在本地。以免下次網路不好的時候,我們而已直接在本地拿資料來繪製T