从ObjectInputStream读取Object时,我收到ClassNotFoundException。正在发送的对象是子类化“WorkUnit”,读取代码具有该引用。似乎接收端抱怨,因为它不知道具体的实现。当我只引用对象的超类时,为什么会关心它:接收端的“WorkUnit”?
从Stream中读取的代码:
private Object readObject() {
Object object = null;
try {
object = objectIn.readObject();
} catch (SocketException | EOFException e) {
// Socket was forcedly closed. Probably means client was
// disconnected
System.out.println("[NetworkHandler] SOCKET CLOSED");
shouldContinue = false;
if (!isClient)
server.clientDisconnected(clientID);
} catch (ClassNotFoundException | IOException e) {
// If shouldContinue is true, we haven't said that we want to close
// the connection
if (shouldContinue) {
e.printStackTrace();
System.err
.println("[NetworkHandler] Error: Couldn't read object correctly");
}
}
return object;
}
工作单位实施:
import java.util.LinkedList;
import java.util.List;
import Application.WorkUnit;
public class WorkUnitImplementation extends WorkUnit<Integer, Integer> {
private static final int INPUT_LENGTH = 1000;
public WorkUnitImplementation() {
super();
setInputLength(INPUT_LENGTH);
}
@Override
public Integer doWork(Integer input) {
wait(50);
return (input % 2 == 1) ? input : null;
}
@Override
public List<Integer> inputFactory(int begin, int end) {
List<Integer> result = new LinkedList<>();
for (int i = begin; i < end; i++) {
result.add(i);
}
return result;
}
private void wait(int time) {
try {
Thread.sleep(time);
} catch (Exception e) {
}
}
}
发送工作单位的代码:
public void uploadWorkUnit(WorkUnit workUnit) {
try {
objectOut.writeObject(new UploadWorkUnit(workUnit));
objectOut.flush();
System.out.println("[NetworkHandler] Uploaded workUnit");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
异常追踪:
java.lang.ClassNotFoundException: WorkUnitImplementation
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at Networking.NetworkHandler.readObject(NetworkHandler.java:188)
at Networking.NetworkHandler.run(NetworkHandler.java:90)
at java.lang.Thread.run(Thread.java:722)
[NetworkHandler]错误:无法正确读取对象
答案 0 :(得分:2)
接收端似乎在抱怨,因为它不知道具体的实现。当我只引用对象的超类时,为什么会关心它:接收端的“WorkUnit”?
这是因为流包含实现类'字段。
来自ObjectOutputStream
javadoc:
对象的默认序列化机制会写入对象的类,类签名以及所有非瞬态和非静态字段的值。
反序列化过程读取流以发现应自动重构的类。它尝试创建该类的新实例,以便它可以使用流中包含的字段填充它。
如果接收端没有与编写的相同的类,它将无效 - 您将获得ClassNotFoundException
。
(也就是说,被序列化的类可以使用writeReplace()
,但这可能超出了这个问题的范围。)
答案 1 :(得分:2)
我有时会遇到同样的问题,我通过将要通过网络发送的类放在它自己的包中(在发送端和接收端)来解决它,然后将其导入到其中的类中被发送或接收。请注意,两端的包结构应该相同。
答案 2 :(得分:0)
作为猜测,您在不同的计算机上运行发送方和接收方。您是否检查过每个字段上是否有相同版本的此类?
答案 3 :(得分:0)
是的,我遇到了同样的问题。我通过在同一个包上使用相同的序列化类来解决它。将ObjectOutputStream和ObjectInputStream函数放在同一个包中并执行输出,然后单独输入或调用。