3

ObjectInputStreamからオブジェクトを読み取るときにClassNotFoundExceptionが発生します。送信されているオブジェクトは、読み取りコードが参照している「WorkUnit」をサブクラス化しています。受信側は特定の実装について知らないため、不平を言っているように見えます。オブジェクトのスーパークラス、つまり受信側の「WorkUnit」のみを参照しているのに、なぜそれを気にするのでしょうか。

ストリームから読み取るコード:

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]エラー:オブジェクトを正しく読み取ることができませんでした

4

4 に答える 4

2

私は時々同じ問題を抱えていましたが、ネットワーク経由で送信されるクラスを独自のパッケージ(送信側と受信側の両方)に入れて解決し、それを送信先のクラスにインポートするか、受け取った。パッケージ構造は両端で同じでなければならないことに注意してください。

于 2012-12-09T21:19:58.640 に答える
2

特定の実装について知らないため、受信側が不平を言っているようです。受信側でオブジェクトのスーパークラス「WorkUnit」のみを参照しているのに、なぜそれを気にするのでしょうか?

これは、ストリームが実装クラスのフィールドで構成されているためです。

ObjectOutputStreamjavadocから:

オブジェクトのデフォルトのシリアライゼーション メカニズムは、オブジェクトのクラス、クラス シグネチャ、すべての非一時的および非静的フィールドの値を書き込みます。

逆シリアル化プロセスは、ストリームを読み取り、自動的に再構成する必要があるクラスを検出します。そのクラスの新しいインスタンスを作成して、ストリームに含まれるフィールドを設定できるようにします。

受信側に書かれたものと同じクラスがない場合、それは機能しませんClassNotFoundException

(つまり、シリアル化されるクラスは を使用できますwriteReplace()が、それはおそらくこの質問の範囲を超えています)。

于 2012-05-07T09:24:35.843 に答える
0

推測として、送信者と受信者を異なるマシンで実行しています。各フィールドにこのクラスの同じバージョンがあることを確認しましたか?

于 2012-05-07T09:22:50.337 に答える
0

ええ、私は同じ問題を抱えていました。同じパッケージで同じシリアル化されたクラスを使用して解決しました。ObjectOutputStream と ObjectInputStream 関数を同じパッケージに入れ、出力を実行してから入力するか、個別に呼び出します。

于 2016-08-23T16:29:21.867 に答える