【问题标题】:Sending Java object of an unknown class发送未知类的 Java 对象
【发布时间】:2013-02-11 23:02:40
【问题描述】:

找了很久,没找到答案:

我有一个服务器,我有一个客户端。服务器应该通过ObjectInputStreamObjectOutputStream 接收一个对象。这已经适用于服务器上已知的任何class。 现在我想发送服务器不知道的classObject。他只知道那个类的接口。这显然失败了......

如何避免ClassNotFoundException?我认为接口是解决方案。我只想通过接口访问我知道的功能,但是Java无论如何都想拥有这个类。

谢谢。

【问题讨论】:

  • 服务器上是否存在接口?
  • 是的,接口在服务器上。

标签: java classnotfoundexception objectoutputstream objectinputstream


【解决方案1】:

没有办法。为了能够在对象上执行方法,您需要拥有对象的具体类的字节码。它的接口不够用。

【讨论】:

  • 好吧,这不是我喜欢听到的 ;-)
  • 那么在收到我的对象之前,我会将 .class 发送到服务器并加载它。
  • @JBNizet “没有办法”对我来说听起来不像是一个答案。其实有一些方法,即在发送对象之前发送.class文件。
  • @MatthiasNiemann 您需要让服务器从客户端接收 .class 文件,创建能够加载这些类的 ClassLoader 实例,然后以某种方式告诉 ObjectInputStream 使用这个不是一项微不足道的任务,因为ObjectInputStream 是一个……em……奇怪的设计。但是,“没有办法”对我来说听起来不是正确的答案。
  • 我的意思是“没有办法”在没有字节码的情况下加载对象。当然,您可以设计一个系统,其中类的字节码在对象之前发送,并使用特定的类加载器来加载类并实例化对象。但这是一项非常艰巨的任务。仅仅发送对象的类是不够的。您还需要递归地发送其依赖项。而且您最好不要对发送的每个对象都这样做。所以它非常非常非常远非微不足道,我不建议这样做。
【解决方案2】:

只有当 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);

【讨论】:

  • 我已经想到了——但我想访问该对象中的一个方法,而不仅仅是其中的数据。
  • @MatthiasNiemann 如果你需要方法,那么你肯定需要类的.class 文件在服务器上可用,因为方法的逻辑在类中,而不是在对象中。考虑将.class 文件从客户端发送到服务器。
  • 还有其他方法。例如,您可以使用 RMI 而不是序列化来发送对象。在这种情况下,当服务器对接收到的对象调用方法时,调用将被编组到客户端,客户端将执行该方法并将结果发送回服务器。
  • 我相信 RMI 只为传递的对象定义了不同的通道。问题仍然是一样的。不过,这是一个我一直在思考的非常有趣的问题。
  • @MarianP RMI 仅传递对象标识(即引用),而不传递对象本身。
【解决方案3】:

你需要特定类的字节码在服务器上,所以它不会像你想象的那样工作。

您可以发送客户端和服务器都知道的类的代理对象。代理将包含服务器未知的类的对象,其类将作为字节数组存储在代理中。代理类将是 Externalizable 并在代理对象反序列化时使用 Classloader.defineClass 在服务器 JVM 中动态创建未知类(使用具有类定义的字节数组从客户端传递)。它不会很快,但可以进行优化,例如不发送和加载类的定义两次等。

如果您需要直接在从客户端传递的对象上调用接口特定方法,请让代理实现您的接口并在代理对象(java.lang.reflect.Proxy/InvocationHandler)上使用动态代理模式来传递调用到以前未知类的代理对象。

这相当复杂,但我相信可以这样做。

【讨论】:

  • 在不同答案下进行了一些讨论后,值得注意的是,还需要发送类的依赖项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多