背景描述:

项目是普通的java服务,以jar包的形式部署,前几天升级了一下服务,部署运行后跟踪日志发现时不时抛异常信息。

具体报错信息如下:

class="linux">[2013-09-22 17:30:53,653] - [pool-3-thread-3] - ERROR - Caught IOException decoding 1061 bytes of data

java.io.InvalidClassException: com.chenzhou.test.model.VmCategoryMapper; local class incompatible: stream classdesc serialVersionUID = 1411005385568342784, local class serialVersionUID = -2356515191808014047

根据报错信息来看,是在反序列化VmCategoryMapper对象时发现serialVersionUID不一致,所以抛了IO异常。

?

我查看了一下VmCategoryMapper类的代码,具体如下(属性和方法就省略了):

package com.chenzhou.test.model;

import java.io.Serializable;

import java.util.List;

public class VmCategoryMapper implements Serializable {

/**

* serialVersionUID:序列化ID.

*/

private static final long serialVersionUID = -2356515191808014047L;

//省略了属性和方法

}

很纳闷的是,Eclipse给我自动生成的serialVersionUID就是-2356515191808014047,那异常信息声明中的反序列化得到的1411005385568342784是怎么得来的呢。

?

我通过SVN历史查看了一下VmCategoryMapper类的版本历史记录,发现历史版本中也没有使用过1411005385568342784作为serialVersionUID。

不过还是发现了一个线索,就是升级之前,VmCategoryMapper类我并没有显示地定义serialVersionUID,这次在优化代码的时候使用IDE自动生成了一个非默认的序列化ID。熟悉java序列化的人应该都了解,如果类实现了Serializable但是没有显式声明serialVersionUID,那么在程序编译时会自己生成这个版本序列化ID,所以我猜测1411005385568342784应该是我服务升级前默认生成的序列化ID。

?

但是问题依然存在,我升级后明明已经显示声明了serialVersionUID的值,为什么反序列化时会得到原来默认的值呢。我把线上的jar包中的VmCategoryMapper类的class文件进行了反编译,发现反编译出来的serialVersionUID是我代码中显示声明的值,也就是-2356515191808014047。说明jar包是正常的。

?

百思不得其解后,同事提醒我,什么时候会进行序列化和反序列化?

经他一提醒,我突然想到了对象在缓存中读取和更新时会进行序列化反序列化,很可能是缓存惹的祸,于是赶紧检查了一下缓存逻辑所在的DAO层的方法:

?

@ReadThroughSingleCache(namespace = CacheConst.VM_CATEGORY, expiration = 3600)

public List getVMCategorys(@ParameterValueKeyProvider String code) {

//get VmCategoryMapper from db

}

Dao中对VmCategoryMapper的读取方法见上面的代码,我们项目中使用了simple-spring-memcached来进行缓存管理。expiration = 3600代表超时时间为1个小时。因为我在服务升级时并没有清理缓存,所以memcached中存在有未超时的缓存对象。这些缓存对象是在升级前存入缓存的,序列化时使用的是原来的默认serialVersionUID也就是1411005385568342784,当服务升级后,由于新的VmCategoryMapper中显示声明了serialVersionUID的值为-235651519180801404,所以如果当查询VmCategoryMapper时,缓存命中,取出memcached中的对象进行反序列化,就会导致serialVersionUID不一致。

定位了原因之后,我把整个memcached进行了flush_all,果然,再也没有抛出该异常了。

这个问题虽然简单,不过还是蛮有意思,值得总结。

java 序列化 缓存_由缓存导致的一个java序列化问题相关推荐

  1. eclipse java工程目录_转载:Eclipse下的java工程目录

    对新手来讲,一个Java工程内部的多个文件夹经常会让大家困惑.更可恶的是莫名其妙的路径问题,在Eclipse编写Java程序中,出现频率最高的错误很可能就是路径问题. 这些问题原因其实都是一个,就是关 ...

  2. Interview:Java岗位面试—面试求职攻略之一个JAVA程序员面试心得(非常值得收藏)

    Interview:Java岗位面试-面试求职攻略之一个JAVA程序员面试心得(非常值得收藏) 导读 据网上资料显示:2018年互联网行业是寒冬,其他行业日子也不好过.各个互联网大厂纷纷缩招减员,严格 ...

  3. 京东java多级缓存_多级缓存设计详解 | 给数据库减负,刻不容缓!

    来这里找志同道合的小伙伴! 作 者 简 介 王梓晨 自古兵家多谋,<谋攻篇>,"故上兵伐谋,其次伐交,其次伐兵,其下攻城.攻城之法,为不得已",可见攻城之计有很多种,而 ...

  4. java一级缓存二级缓存_一级缓存和二级缓存的理解

    首先补充下CPU的知识: CPU也就是中央处理器,相当于计算机的大脑: CPU是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Unit): CPU功能主要是解 ...

  5. syslog 向内存中缓存_漫谈缓存(Cache)、大规模芯片系统的存储层次结构优化以及开源仿真工具ZSim...

    这次的话题将从缓存开始,以一种易于理解的方式向大家呈现缓存的基本概念,然后拓展至大规模芯片系统的非均一访问延时的缓存访问问题,最后简要介绍一种缓存仿真工具--ZSim. 缓存的概念 处理器和内存之间存 ...

  6. mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存

    设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --><settings& ...

  7. java中异常+连接重置_是什么导致我的java.nett.ocketException:连接重置?

    是什么导致我的java.nett.ocketException:连接重置? 我们看到了频繁但断断续续的情况.java.net.SocketException: Connection reset我们日志 ...

  8. mysql 的几种缓存_数据库缓存的几种方式

    数据库缓存的几种方式 引入缓存可以提高性能,但是数据会存在两份,一份在数据库中,一份在缓存中,如果更新其中任何一份会引起数据的不一致,数据的完整性被破坏了,因此,同步数据库和缓存的这两份数据就非常重要 ...

  9. Java并发插件_五分钟,轻松掌握Java并发编程!

    Java作为最流行的编程语言之一,随着 Java 8的到来,越来越多的人开始学习,并深入研究!下面将介绍 Java并发编程,让开发者在最短的时间里掌握并发编程. 1. 并发 1.1. 什么是并发? 并 ...

  10. java核心面试_前100多个核心Java面试问题

    java核心面试 Core Java interview questions help you in preparing for java based interviews. Whether you ...

最新文章

  1. java负数右移_收入囊中篇---Java程序基础(二)
  2. Coursera在线学习---第十节.大规模机器学习(Large Scale Machine Learning)
  3. 算法导论中C语言代码,算法导论-学习笔记与进度
  4. 鸿蒙开源小米能用吗,鸿蒙2.0开源,任何品牌都可以使用!小米用不用?
  5. Auto.JS 教程
  6. URAL 1013 K-based Numbers. Version 3
  7. 中科大基础数学博士招生放大招 年收入10万吸引生源
  8. python怎么导入数据集keras_python – 如何为Keras准备数据集?
  9. 灰度资产管理总规模突破420亿美元
  10. Layui自定义表单校验规则
  11. Mysql Mac版下载安装教程
  12. 计算机开机错误62,电脑出现Error 1962怎么办 电脑启动报错Error 1962的解决方案介绍...
  13. duilib开发(七):复杂控件介绍
  14. 阿帕奇服务器搭建网站,使用Apache搭建Web网站服务器
  15. 手机status500_HTTP Status 500 - 是什么意思
  16. 鼠标切换虚拟桌面 autohotkey
  17. Office噩梦公式远程代码执行漏洞
  18. Exception in Thread: ValueError: signal number 32 out of range
  19. ubuntu下ati驱动安装
  20. 【自然语言处理】gensim的word2vec

热门文章

  1. mac azure git_将Azure Data Studio与Git和GitHub集成
  2. iText 生成复杂表格
  3. git更新pull报错Pulling 1 repository Remote does not have refs/heads/rel5.1 available for fetch
  4. [EffectiveC++]item06:若不想使用编译器自动生成的函数,就该明确决绝
  5. loj10147. 「一本通 5.1 例 1」石子合并
  6. 简单的跑马灯效果(轮播图)
  7. JavaScriptCore.framework基本用法(一)
  8. QQ邮箱发送邮件,出现mail from address must be same as authorization user错误
  9. 解决Lost connection to MySQL server at 'reading initial communication packet', 的方法
  10. JSTL与JAVA数据交互 pagecontext