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操作是致命的。
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android(安卓)Toast 总结
- framework下资源文件---自定义统一的系统风格
- android文件上传示例分享(android图片上传)
- 在Android下实现鼠标右键返回
- Android开发应用异步检查更新代码