哪些RMI异常表示连接丢失

时间:2011-07-27 14:20:12

标签: java rmi

我正在使用以下代码来通知远程(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异常列表,表明远程对象(或整个服务器)丢失/断开?

3 个答案:

答案 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,除了:

  • UnmarshalException
  • UnexpectedException
  • SERVERERROR

答案 2 :(得分:0)

这是一个复杂的问题。它们中的大多数根本没有表明丢失的连接,事实上只有UnmarshalException才能真正做到这一点,并且只有时候,例如,当它包装ClassNotFoundException时,它不表示连接丢失。

在某种意义上,ConnectIOException也表示,但只有在尝试在调用开始时恢复池化客户端连接时才会发生。

一个更有趣,更复杂的问题是,如果你在它们之后重试,哪些异常会保留幂等性,这是一个非常难以回答的问题。我将大约20页的RMI书用于此,我怀疑我是否涵盖了所有可能性。

NoSuchObjectException指示导出正在调用的存根的远程对象不再存在,即已从其JVM中导出。

RemoteException本身几乎可以表示任何事情,特别是如果你错误地让你自己的应用程序异常扩展它。不要那样做。实际上,您不应该只是自己捕获RemoteException,您应该使用底部的catch-all RemoteException捕获器分别捕获所有可能的RMI异常,因为不同的异常有不同的恢复策略。除非你只是想放弃任何远程错误。