5

所以现在,我有一台运行ObjectInputStreamand的服务器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 知道类,它不发送类定义。特别是,当您序列化一个Class对象时,您不会发送该类的字节码,而只是指示接收 VM 查找Class具有特定名称的类的对象。

还要注意,一个Class对象代表一个在JVM 中定义的类,即该类的字节码已经被加载。在加载类尝试编译到类以生成该字节码几乎没有意义。

因此,我们需要以某种方式将类定义提供给客户端。最简单的方法是像客户端需要的任何其他类一样执行此操作(通过将其打包到客户端的 jar 文件中,或者您用来安装客户端程序的任何方式)。如果这不可能,您可以通过网络加载类定义,例如使用 a 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 回答