Java 向后兼容性:readObject() 如何读取具有不同 serialVersionUID 的相同类名对象?
Java backward-compatibility: how readObject() read same classname objects with different serialVersionUID?
这个套接字将继续接收一些旧对象和新对象
一样的名字。但是,如果我直接使用 readObject,它会抛出
致命异常。我们中的一些人会建议忽略旧对象或
更改旧的目标代码。这对我来说是不可能改变的
客户端代码。我需要处理
向后兼容性。
Socket s = ss.accept();
ObjectInputStream lvStream = new ObjectInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 1L;
}
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 2L;
}
// The new class in my local ( 1L or 2L still would not solve the issue easily )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 2L;
}
在readObject()的那一行,
我遇到了这个致命异常:
java.io.InvalidClassException 本地 class 不兼容:流 classdesc serialVersionUID = 1,本地 class serialVersionUID = 2
如何读取这两种 Apple 对象数据(Hashmap)?
谢谢。
Java: how can readObject()
read two classes with different serialVersionUID
?
很容易。它们是不同的 classes。为什么不呢?
There are two class with same name but different in serialVersionUID.
所以它们是不同的class。你的问题?
I got this fatal exception:
java.io.InvalidClassException local class incompatible : stream classdesc serialVersionUID = 2, local class serialVersionUID = 1
这与在不同包中具有相同名称的两个 class 没有任何关系。这意味着您在发送方部署了 class 的 serialVersionUID = 2
版本,而在接收方部署了 serialVersionUID = 1
的不同版本。苏蒂安:不要那样做。部署相同的版本:在本例中,带有 2
的版本,因为它是流中的版本。一般而言,您应该不在不知道确切您在做什么的情况下更改serialVersionUID
值。
In my case, there are two versions class sending to my side. 1L and 2L.
不,没有。有一个发送版本,2L,和一个不同版本的接收,1L。不要那样做。
只要我们扩展ObjectInputStream,
我们将有权访问流 SerialVersionUID 以与本地 SerialVersionUID 进行比较。
Socket s = ss.accept();
// use the extended ObjectInputStream ( DecompressibleInputStream )
DecompressibleInputStreamlvStream = new DecompressibleInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
public class DecompressibleInputStream extends ObjectInputStream {
public DecompressibleInputStream(InputStream in) throws IOException {
super(in);
}
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
Class<?> localClass;
try {
localClass = Class.forName(resultClassDescriptor.getName());
} catch (ClassNotFoundException e) {
System.err.println("No local class for " + resultClassDescriptor.getName());
return resultClassDescriptor;
}
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
if (localClassDescriptor != null) {
final long localSUID = localClassDescriptor.getSerialVersionUID();
final long streamSUID = resultClassDescriptor.getSerialVersionUID();
if (streamSUID != localSUID) {
System.err.println("Potentially Fatal Deserialization Operation.");
resultClassDescriptor = localClassDescriptor;
}
}
return resultClassDescriptor;
}
}
希望对您有所帮助
(感谢此 post)
这个套接字将继续接收一些旧对象和新对象 一样的名字。但是,如果我直接使用 readObject,它会抛出 致命异常。我们中的一些人会建议忽略旧对象或 更改旧的目标代码。这对我来说是不可能改变的 客户端代码。我需要处理 向后兼容性。
Socket s = ss.accept();
ObjectInputStream lvStream = new ObjectInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 1L;
}
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 2L;
}
// The new class in my local ( 1L or 2L still would not solve the issue easily )
public class Apple extends HashMap<String, String> {
private static final long serialVersionUID = 2L;
}
在readObject()的那一行, 我遇到了这个致命异常:
java.io.InvalidClassException 本地 class 不兼容:流 classdesc serialVersionUID = 1,本地 class serialVersionUID = 2
如何读取这两种 Apple 对象数据(Hashmap)?
谢谢。
Java: how can
readObject()
read two classes with differentserialVersionUID
?
很容易。它们是不同的 classes。为什么不呢?
There are two class with same name but different in serialVersionUID.
所以它们是不同的class。你的问题?
I got this fatal exception:
java.io.InvalidClassException local class incompatible : stream classdesc serialVersionUID = 2, local class serialVersionUID = 1
这与在不同包中具有相同名称的两个 class 没有任何关系。这意味着您在发送方部署了 class 的 serialVersionUID = 2
版本,而在接收方部署了 serialVersionUID = 1
的不同版本。苏蒂安:不要那样做。部署相同的版本:在本例中,带有 2
的版本,因为它是流中的版本。一般而言,您应该不在不知道确切您在做什么的情况下更改serialVersionUID
值。
In my case, there are two versions class sending to my side. 1L and 2L.
不,没有。有一个发送版本,2L,和一个不同版本的接收,1L。不要那样做。
只要我们扩展ObjectInputStream,
我们将有权访问流 SerialVersionUID 以与本地 SerialVersionUID 进行比较。
Socket s = ss.accept();
// use the extended ObjectInputStream ( DecompressibleInputStream )
DecompressibleInputStreamlvStream = new DecompressibleInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
public class DecompressibleInputStream extends ObjectInputStream {
public DecompressibleInputStream(InputStream in) throws IOException {
super(in);
}
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
Class<?> localClass;
try {
localClass = Class.forName(resultClassDescriptor.getName());
} catch (ClassNotFoundException e) {
System.err.println("No local class for " + resultClassDescriptor.getName());
return resultClassDescriptor;
}
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
if (localClassDescriptor != null) {
final long localSUID = localClassDescriptor.getSerialVersionUID();
final long streamSUID = resultClassDescriptor.getSerialVersionUID();
if (streamSUID != localSUID) {
System.err.println("Potentially Fatal Deserialization Operation.");
resultClassDescriptor = localClassDescriptor;
}
}
return resultClassDescriptor;
}
}
希望对您有所帮助
(感谢此 post)