So right now, I have a server that is running with ObjectInputStream
and ObjectOutputStream
.
The problem I am having is that I have a custom (anonymous) class that extends java.lang.Date
that I am trying to send to the client and then compile.
So nowhere do I ever define the class on the client side, but I want to compile the class programmatically. I have tried many different methods, but every time I get a ClassNotFoundException
because the class isn't on the client side initially.
Class<?> dateClass = (Class<?>) in.readObject(); //This is where the CNF Exception occurs
Compiler.compileClass(dateClass);
The Java Serialization mechanism assumes the classes are known to the deserializing JVM, it doesn't send the class definitions. In particular, when you serialize a Class
object, you don't send the byte code for that class but only instruct the receiving VM to look up the Class
object for a class with a particular name.
Also note that a Class
object represents a class defined in the JVM, i.e. the class' bytecode has already been loaded. It makes little sense to try to compile to class to generate that bytecode after loading the class.
So, we need to somehow get the class definition to the client. The easiest approach is to do this like any other class the client needs (by packing it in the client's jar file, or whatever means you use to install the client programm). If that is not possible, you could load the class definition over the network, for instance by using a URLClassLoader
, or you could send the classfile through the serialization stream, and upon receiving it on the client use ClassLoader.defineClass
to load the class.
PS: This issue is completely indepedent of whether the class is named or not. The following test code shows that objects of anonymous classes can be serialized and deserialized just fine (if the receiving VM has the class definition):
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With