我必须使用大量已编译的Java类,这些类没有明确指定serialVersionUID.因为他们的UID是由编译器任意生成,其中很多需要的类的被序列化和反序列化最终导致例外,即使实际的类定义匹配.(当然,这是所有预期的行为.)
我回过头来修复所有这些第三方代码是不切实际的.
因此,我的问题是:有没有什么办法可以使Java运行时忽略在serialVersionUIDs差异,只有失败的时候有在结构上的实际差异进行反序列化?
Eclipse很好地为我生成了serialVersionUID.但这似乎是被动代码生成,因为我更改文件时id不会自动更新,除非我再次生成代码.
有没有办法在每次更改内容时生成serialVersionUID?"保存行动"似乎没有包含这样的选项 - 有人找到了某种方法来做到这一点吗?
它可以与IDE保存操作或类似的东西结合使用,这样我可以恢复更改,如果我这样做不会影响序列化.
此致,Touko
编辑:@gustafc:这有两点要点:
这听起来合情合理吗?
Summa summarum,经过多思考后,每次更改时自动递增的serialVersionUID会更好......
我的客户端有一个oracle数据库,一个对象通过objOutStream.writeObject持久化为blob字段,该对象现在有一个不同的serialVersionUID(即使对象没有变化,可能是不同的jvm版本),当他们尝试反序列化时抛出异常:
java.io.InvalidClassException: CommissionResult; local class incompatible:
stream classdesc serialVersionUID = 8452040881660460728,
local class serialVersionUID = -5239021592691549158
Run Code Online (Sandbox Code Playgroud)
它们serialVersionUID从一开始就没有为固定值赋值,所以现在有些东西改变了抛出异常.现在他们不想丢失任何数据,为此我认为最好的方法是读取对象,对它们进行反序列化,然后通过XMLEncoder再次保存它们,以避免将来出现类似当前"类不兼容"错误的错误.
显然有对2个不同的值serialVersionUID持续了那个对象,所以我想读取数据,尝试用一个值,如果失败则与其他值尝试,要做到这一点我已经试过改变serialVersionUID类使用
的ASM api.我已经能够更改值,但问题是如何激活类上的更改,因此当它被反序列化时,objInpStr.readObject()将我的修改版本的类与我的特定serializedVersionUID.我做了一个测试类来模拟真实的环境,我拿一个对象(它具有不同serialVersionUID问题的对象Reservation属性)对象名称属性是
CommissionResult:
public class Reservation implements java.io.Serializable {
private CommissionResult commissionResult = null;
}
public class CommissionResult implements java.io.Serializable{
}
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.SerialVersionUIDAdder;
public class SerialVersionUIDRedefiner extends ClassLoader {
public void workWithFiles() {
try {
Reservation res = …Run Code Online (Sandbox Code Playgroud) 我刚刚开始使用AWT并在其中制作了一个简单的程序,它工作正常,但它在eclipse中显示了一条我不明白的警告信息:
可序列化类TestGUI不声明long类型的静态最终serialVersionUID字段
我知道警告消息与AWT无关,并且没有必要发布我的整个代码,但是当我试图制作代码的SSCCE时,警告也消失了.由于我不知道为什么会产生这个警告,所以我不知道在我的SSCCE中保留哪一部分.因此整个代码!
我的代码是:
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestGUI extends Frame {
/**
* @param args
*/
private int x = 50;
private int y = 50;
TestGUI(String s) {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
setVisible(false);
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
x = me.getX();
y = me.getY();
repaint();
}
});
}
public void paint(Graphics g) {
g.drawString("Hello Princess", 100, 100);
g.drawString("Mouse …Run Code Online (Sandbox Code Playgroud) 有没有办法在Eclipse中串行生成serialVersionUID?通过串行我想要的意思是,如果一个可序列化的类具有serialVersionUID = 1L,那么当我生成另一个类的serialVersionUID时,这将是serialVersionUID = 2L.
如果我手动指定1L,2L,3L等,这会产生任何问题吗?
Eclipse提供了一个选项"选择添加生成的串行版本ID",这个选项可以安全选择吗?
为什么不serialVersionUID自动生成?我在应用程序服务器上遇到了一个问题,显然是在缓存旧类.
作为调试应用程序的一部分,我注意到Field.getDeclaredFields()返回一些合成字段,包括serialVersionUID扩展接口的类中的字段,尽管没有扩展Serializable.
为什么编译器会添加这样的字段?
UPDATE
事实上,还有一个$VRc合成领域.
我正在做一个项目,我们有大量的对象被序列化并使用pickle/存储到磁盘cPickle。
随着项目生命周期的进展(在向现场客户发布之后),未来的功能/修复可能需要我们更改一些持久对象的签名。这可能是添加字段、删除字段,甚至只是更改一段数据的不变量。
有没有一种标准的方法来标记一个对象,该对象将被腌制为具有某个版本(如serialVersionUID在 Java 中)?基本上,如果我正在恢复 Foo 版本 234 的实例,但当前代码是 236,我希望收到一些有关 unpickle 的通知。我是否应该继续推出我自己的解决方案(可能是 PITA)。
谢谢
我正在开发一个生成Java文件的项目.我希望能够像serialVersionUID使用serialver工具一样添加.
有没有办法在生成Java代码时执行此操作,还是需要让该工具的用户手动提供UID?要清楚,我不打算通过Eclipse或serialver工具自动执行此操作,而是通过Java本身执行此操作.
我目前正在测试远程演员在Android和Windows之间进行通信.Actors远程发送不同的类,我设置serialVersionUID.
这是我的序列化类的代码:
@SerialVersionUID(13.asInstanceOf[Long]) case class IdentifyMessage(userName : String, user : User, code : Int)
Run Code Online (Sandbox Code Playgroud)
问题是远程actor调试说不兼容的类存在问题:
caught java.io.InvalidClassException: scala.actors.remote.Node; local class incompatible:
stream classdesc serialVersionUID = -6610463074147725500, local class serialVersionUID = -7525549079045563153
Run Code Online (Sandbox Code Playgroud)
为什么我的SerialVersionUID对编译器无关紧要?
如何修复serialVersionUID?或者可能还有另一个问题?
谢谢