java io报错_解决错误java.io.InvalidClassException

今天遇到一个现场问题,任务报错java.io.InvalidClassException。在开发环境是没有报错的,正式环境报错。大概类似于下面这样(非报错原文,摘自网上同类博客)

在网上查找资料后了解到 :

该异常是由于反序列化时, 当前类的serialVersionUID 与 反序列化后的类的serialVersionUID 不同所致。在未显示声明情况下由java编译器计算得出,但是不同的java编译器可能计算出的结果不同(本次出现该问题的直接原因是spark各个节点接收到的是sparksql  jar包不一致),因此强烈推荐显式声明serialVersionUID 。

声明方法如下:

@SerialVersionUID(1234567890L) classxxx() extends yyy with Serializable {

......

}

问题补充:

1、如何查看类的serialVersionUID,

针对java的话,可以使用 serialver命令。  首先解压想查询类所在jar包,然后cd至解压目录,serialver 完整类名  ,即可得到serialVersionUID

针对Scala  不推荐使用serialver,使用serialver时,不包含scala标准库,会报错找不到scala Serializable类,建议直接使用代码查询

下面提供了一个例子读取类中的serialVersionUID

@SerialVersionUID(1l) case classIdentifyMessage1(userName: String, code: Int)

@SerialVersionUID(12l) case classIdentifyMessage2(userName: String, code: Int)objectSerializationClass {

def main(args: Array[String]): Unit={

println("#1" + java.io.ObjectStreamClass.lookup(IdentifyMessage1("hei", 7).getClass).getSerialVersionUID)

println("#2" + java.io.ObjectStreamClass.lookup(IdentifyMessage2("hei", 8).getClass).getSerialVersionUID)

println("#3" +com.sun.corba.se.impl.io.ObjectStreamClass.ObjectStreamClass.getActualSerialVersionUID(IdentifyMessage1("hei", 8).getClass))

println("#4" +com.sun.corba.se.impl.io.ObjectStreamClass.ObjectStreamClass.getSerialVersionUID((IdentifyMessage1("hei", 8).getClass)))

}

}

不过虽然这个例子是我写的,但是我也还有没弄懂的地方,本例子在本地单机环境下运行是不会更改SerialVersionUID的。这个问题如果有大神知道的话,欢迎留言

67952523c30cef92ca49c89613b6c7a0.png

但是在spark里面是可以生效的。(两者java版本一直)

f9e5f7983a2c7b3b86c66f5fa45a96a0.png

附上关于Serializable接口的说明

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

If a serializableclass does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值