我写了这个小程序来说明我的问题(这本身并没有多大意义,但这并不重要):
public class Stuff extends UnicastRemoteObject implements IStuff{
HashMap<Entry, String> map = new HashMap<Entry, String>();
@Override
public void exec(IStuff s) throws RemoteException{
System.out.println(s.getEntryMap(this.e1));
System.out.println(s.getEntryMap(this.e2));
System.out.println(s.getEntryMap(this.e3));
}
}
假设有一个类 Entry (也扩展UnicastRemoteObject
)并且 HashMap 填充在构造函数中。还有:
public class MyRegistry extends UnicastRemoteObject implements IMyRegistry{
@Override
public void register(IStuff s) throws RemoteException{
s.exec(s);
}
}
当我现在打电话时
MyRegistry r = new MyRegistry();
r.register(new Stuff());
它按预期打印地图的内容。
如果MyRegistry
实例在服务器上运行,则会发生不同的事情:
服务器启动MyRegistry
:
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
reg.rebind("Reg",new MyRegistry());
客户使用它:
IMyRegistry reg = (IMyRegistry) Naming.lookup("Reg");
reg.register(new Stuff());
它现在打印的只是:
null
null
null
这是有道理的,因为 Registry 获取了一个 Remote Stub,并将其传递给该exec
方法。该方法本身远程exec
调用,因为它接收到 Stub of Stuff。因此,使用 e1、e2 和 e3 的 Stub 调用该方法。当然,地图没有存根的条目,而是实际对象的条目。收到的实例不是实例条目。getEntryMap
getEntryMap
IEntry
getEntryMap
我现在的问题是:
- 我怎样才能解决这个问题?在任何情况下,我都想
exec
显示正确的条目。有没有办法将存根转换为实际对象?基本铸造显然不起作用。似乎以某种方式这应该是可能的,因为Stuff
,map
和条目存在于客户端上,并在exec
客户端上执行。 - 为什么客户端没有注意到服务器返回了一个实际存在于我的环境中的存根?
- 在那之后,为什么不是每个条目存根
getEntryMap() instanceof Entry
,甚至不是同一个对象?
编辑,附加信息:
创建的实际Stuff
对象如下所示:
Stuff[UnicastServerRef [liveRef: [endpoint:[192.168.1.68:60327](local),objID:[-1ff30562:13f0eb9f539:-7ff9, 219978949996152147]]]]
存根exec
看起来像这样:
Proxy[IStuff,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:[192.168.1.68:60327](remote),objID:[-1ff30562:13f0eb9f539:-7ff9, 219978949996152147]]]]]
基本上,它归结为:
- 实际对象和存根看起来相同,除了存根被“包装”在代理事物中。
- 由于
Stuff
是 aUnicastRemoteObject
,并且客户端始终跟踪导出的对象,因此将存根解析为实际对象似乎不应该太难。