java 从流中读取对象时的Java ClassNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10479481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:14:20  来源:igfitidea点击:

Java ClassNotFoundException when reading object from a stream

javaserializationobjectinputstream

提问by rynojvr

I am getting a ClassNotFoundException when reading an Object from an ObjectInputStream. The object that is being sent is subclassing "WorkUnit" which the reading code has a reference to. It would seem that the receiving end is complaining because it doesn't know about the specific implementation. Why would it care about that when I'm only referencing the object's superclass: "WorkUnit" on the side that is receiving?

从 ObjectInputStream 读取对象时,我收到 ClassNotFoundException。正在发送的对象是读取代码引用的“WorkUnit”的子类。接收端似乎在抱怨,因为它不知道具体的实现。当我只在接收方引用对象的超类:“WorkUnit”时,它为什么会关心这个?

Code to read from Stream:

从 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;
}

Work Unit Implementation:

工作单元实施:

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) {

    }
}
}

Code to send Work Unit:

发送工作单元的代码:

    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();
    }
}

Exception Trace:

异常跟踪:

java.lang.ClassNotFoundException: WorkUnitImplementation
at java.net.URLClassLoader.run(URLClassLoader.java:366)
at java.net.URLClassLoader.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] Error: Couldn't read object correctly

[NetworkHandler] 错误:无法正确读取对象

采纳答案by Greg Kopff

It would seem that the receiving end is complaining because it doesn't know about the specific implementation. Why would it care about that when I'm only referencing the object's superclass: "WorkUnit" on the side that is receiving?

接收端似乎在抱怨,因为它不知道具体的实现。当我只在接收方引用对象的超类:“WorkUnit”时,它为什么会关心这个?

It's because the stream consists of the implementationclass' fields.

这是因为流由实现类的字段组成。

From ObjectOutputStreamjavadoc:

来自ObjectOutputStreamjavadoc:

The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields.

对象的默认序列化机制写入对象的类、类签名以及所有非瞬态和非静态字段的值。

The deserialisation process reads the stream to discover the class that should be automagically reconstituted. It tries to create a new instance of that class so that it can then populate it with the fields that are contained in the stream.

反序列化过程读取流以发现应该自动重构的类。它尝试创建该类的新实例,以便随后可以使用流中包含的字段填充它。

If the receiving end doesn't have the same class that was written, it won't work -- you'll get a ClassNotFoundException.

如果接收端没有编写的同一个类,它就不会工作——你会得到一个ClassNotFoundException.

(That said, the class being serialised could use writeReplace(), but that's probably beyond the scope of this question).

(也就是说,被序列化的类可以使用writeReplace(),但这可能超出了这个问题的范围)。

回答by tunmyse

I had the same problem sometimes and I solved it by putting the class that's to be sent over the network in a package of its own (both on the sending end and the receiving end) and then import it into the class where its being sent or received. Note that the package structure should be the same on both ends.

我有时遇到同样的问题,我通过将要通过网络发送的类放在自己的包中(在发送端和接收端)然后将其导入到发送或已收到。请注意,两端的封装结构应相同。

回答by Irene Maryanne

Yea, I had the same problem. I have solved it by using the same serialized class on the same package. Put ObjectOutputStream and ObjectInputStream function in the same package and execute output then input or call separately.

是的,我遇到了同样的问题。我已经通过在同一个包上使用相同的序列化类解决了这个问题。将 ObjectOutputStream 和 ObjectInputStream 函数放在同一个包中,分别执行输出然后输入或调用。

回答by robthewolf

As a guess, you are running the sender and the receiver on different machines. Did you check that they have the same version of this class on each field?

作为猜测,您正在不同的机器上运行发送方和接收方。您是否检查过他们在每个领域都有相同版本的此类?