我正在使用以下代码来通知远程(RMI)事件侦听器更改。
// notify remote listeners of this change
ThreadPool.execute(new Runnable() { @Override public void run() {
List<Integer> removal = new ArrayList<Integer>();
listeners.getReadLock().lock();
try {
for (Entry<Integer, RemoteDataServerListener> e : listeners.entrySet()) {
try {
e.getValue().creditsChanged(player.getId(), player.getCredits());
} catch (RemoteException er) {
log.warn("Error in remote listener", er);
// this listener is gone
if (er instanceof NoSuchObjectException) {
log.info("Removing the listener");
removal.add(e.getKey());
}
}
}
} finally {
listeners.getReadLock().unlock();
}
// listeners that are gone don't need future events
listeners.removeAll(removal);
}});
正如您所看到的,我在抛出NoSuchObjectException
时删除了一个侦听器,但这可能不是唯一可以抛出的异常。
是否有完整的RMI异常列表,表明远程对象(或整个服务器)丢失/断开?
答案 0 :(得分:1)
AFAIK,如果您可以确保您的RMI应用程序总是抛出用户定义或自定义异常,无论服务器出现什么问题,捕获RemoteException
并删除监听器应该是好的去。 E.g。
public Object doSomething() throws RemoteException {
Object o;
try {
// application processing
} catch(final Throwable t) {
throw new CustomException(t);
}
return o;
}
答案 1 :(得分:0)
从http://download.oracle.com/javase/6/docs/api/java/rmi/RemoteException.html看起来我可以这样对待所有RemoteExceptions,除了:
答案 2 :(得分:0)
这是一个复杂的问题。它们中的大多数根本没有表明丢失的连接,事实上只有UnmarshalException才能真正做到这一点,并且只有时候,例如,当它包装ClassNotFoundException时,它不表示连接丢失。
在某种意义上,ConnectIOException也表示,但只有在尝试在调用开始时恢复池化客户端连接时才会发生。
一个更有趣,更复杂的问题是,如果你在它们之后重试,哪些异常会保留幂等性,这是一个非常难以回答的问题。我将大约20页的RMI书用于此,我怀疑我是否涵盖了所有可能性。
NoSuchObjectException指示导出正在调用的存根的远程对象不再存在,即已从其JVM中导出。
RemoteException本身几乎可以表示任何事情,特别是如果你错误地让你自己的应用程序异常扩展它。不要那样做。实际上,您不应该只是自己捕获RemoteException,您应该使用底部的catch-all RemoteException捕获器分别捕获所有可能的RMI异常,因为不同的异常有不同的恢复策略。除非你只是想放弃任何远程错误。