5

だから今、私はとで実行されているサーバーを持っていObjectInputStreamますObjectOutputStream

私が抱えている問題はjava.lang.Date、クライアントに送信してからコンパイルしようとしている拡張のカスタム(匿名)クラスがあることです。

したがって、クライアント側でクラスを定義する場所はありませんが、プログラムでクラスをコンパイルしたいと思います。ClassNotFoundException私はさまざまなメソッドを試しましたが、クラスが最初はクライアント側にないため、取得するたびに。

Class<?> dateClass = (Class<?>) in.readObject(); //This is where the CNF Exception occurs
Compiler.compileClass(dateClass);
4

1 に答える 1

7

Javaシリアル化メカニズムは、クラスが逆シリアル化するJVMに認識されていることを前提としており、クラス定義を送信しません。特に、オブジェクトをシリアル化する場合、そのクラスのバイトコードは送信せず、受信側のVMに特定の名前のクラスのオブジェクトClassを検索するように指示するだけです。Class

また、オブジェクトはJVMで定義されたクラスを表すことにも注意してくださいClass。つまり、クラスのバイトコードはすでにロードされています。クラスをロードした後にそのバイトコードを生成するためにクラスにコンパイルしようとすることはほとんど意味がありません。

したがって、どういうわけかクライアントにクラス定義を取得する必要があります。最も簡単なアプローチは、クライアントが必要とする他のクラスと同じようにこれを行うことです(クライアントのjarファイルにパックするか、クライアントプログラムのインストールに使用する手段を使用します)。それが不可能な場合は、たとえば、を使用してネットワーク経由でクラス定義をロードするURLClassLoaderか、シリアル化ストリームを介してクラスファイルを送信し、クライアントで受信したらClassLoader.defineClassクラスのロードに使用できます。

PS:この問題は、クラスに名前が付けられているかどうかに完全に依存していません。次のテストコードは、匿名クラスのオブジェクトを正常にシリアル化および逆シリアル化できることを示しています(受信側のVMにクラス定義がある場合)。

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
        Serializable payload = new Serializable() {
            @Override
            public String toString() {
                return "hello from the anonymous class";
            }
        };
        oos.writeObject(payload);
        oos.writeObject(payload.getClass());
    }

    try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
        System.out.println(in.readObject());
        System.out.println(in.readObject());
    }
于 2012-02-26T00:02:26.060 に答える