简体   繁体   English

从流中读取对象时的Java ClassNotFoundException

[英]Java ClassNotFoundException when reading object from a stream

I am getting a ClassNotFoundException when reading an Object from an ObjectInputStream. 从ObjectInputStream读取Object时,我得到一个ClassNotFoundException。 The object that is being sent is subclassing "WorkUnit" which the reading code has a reference to. 正在发送的对象是子类化“WorkUnit”,读取代码具有该引用。 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”?

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$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] Error: Couldn't read object correctly [NetworkHandler]错误:无法正确读取对象

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 implementation class' fields. 这是因为流包含实现类的字段。

From ObjectOutputStream javadoc: 来自ObjectOutputStream javadoc:

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() ,但这可能超出了这个问题的范围)。

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. 请注意,两端的包结构应该相同。

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? 您是否检查过每个字段上是否有相同版本的此类?

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函数放在同一个包中并执行输出,然后单独输入或调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从资产读取对象时发生ClassNotFoundException(android) - ClassNotFoundException when reading object from assets(android) 从ObjectInputStream读取对象时发生ClassNotFoundException - ClassNotFoundException when reading object from ObjectInputStream 读取对象时发生ClassNotFoundException - ClassNotFoundException when reading object 使用ObjectInputStream从文件中读取对象? ClassNotFoundException - Reading object from file using ObjectInputStream? ClassNotFoundException 从GZipped文件读取对象时发生ClassNotFoundException - ClassNotFoundException in reading object from GZipped file 从ObjectInputStream读取时,服务器上的ClassNotFoundException - ClassNotFoundException on the server when reading from ObjectInputStream Java TCP:从网络读取输入 stream 时缓冲区下溢 - Java TCP: Buffer underflow when reading an input stream from the network Java SerialIzation:反序列化对象时出现“ ClassNotFoundException” - Java SerialIzation: 'ClassNotFoundException' when deserializing an Object 从流中读取时出现IndexOutOfBoundsException - IndexOutOfBoundsException when reading from stream 尝试从字符串解码 object 时出现 ClassNotFoundException - ClassNotFoundException when trying to decode object from String
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM