搜索了很长时间,但没有找到任何答案:
我有一个服务器,我有一个客户端。服务器应该通过ObjectInputStream和接收对象ObjectOutputStream。这已经适用于class服务器上已知的任何 . 现在我想发送一个Object服务器class不知道的。他只知道那个类的接口。这显然失败了......
我怎样才能避免ClassNotFoundException?我认为接口是解决方案。我只想通过接口访问我知道的功能,但是Java无论如何都希望拥有该类。
谢谢你。
搜索了很长时间,但没有找到任何答案:
我有一个服务器,我有一个客户端。服务器应该通过ObjectInputStream和接收对象ObjectOutputStream。这已经适用于class服务器上已知的任何 . 现在我想发送一个Object服务器class不知道的。他只知道那个类的接口。这显然失败了......
我怎样才能避免ClassNotFoundException?我认为接口是解决方案。我只想通过接口访问我知道的功能,但是Java无论如何都希望拥有该类。
谢谢你。
There is no way. To be able to execute a method on an object, you need to have the byte-code of the concrete class of the object. Its interface isn't sufficient.
只有当 JVM 加载了这个类时,某个类的对象才可能存在于 JVM 中。可能与其发送未知类型的对象,不如发送一些描述对象的众所周知的数据结构,即 HashMap。所以,而不是这样做:
MySecretClass o = new MySecretClass ();
o.setFoo ("Hello, World!");
o.setBar (123);
send (o);
您执行以下操作:
Map o = new HashMap ();
o.put ("foo", "Hello, World!");
o.put ("bar", 123);
send (o);
您需要服务器上特定类的字节码,因此它不会像您想象的那样工作。
您可以发送客户端和服务器都知道的类的代理对象。代理将包含服务器未知的类的对象,其类将作为字节数组存储在代理中。当代理对象被反序列化时(使用带有从客户端传递的类定义的字节数组),代理类将是Externalizable并使用Classloader.defineClass在服务器 JVM 中动态创建未知类。它不会很快,但可以进行优化,例如不发送和加载类的定义两次等。
如果您需要直接在从客户端传递的对象上调用接口特定方法,请让代理实现您的接口并在代理对象(java.lang.reflect.Proxy/InvocationHandler)上使用动态代理模式将调用传递给代理以前未知的类的对象。
这相当复杂,但我相信可以这样做。