1

RMI で手を汚しているときに、java.rmi.NoSuchObjectException例外が発生したため、次の質問に至りました: java.rmi.NoSuchObjectException: no such object in table but my question is different .

メインメソッドで、つまりメインスレッドで impl オブジェクトを作成しています。私がこれを行う場合:

FooImpl fi = new FooImpl();
foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);

物事はうまくいきます。

私がこれを行う場合:

foo = (Foo) UnicastRemoteObject.exportObject(new FooImpl(), 0);

FooImpl インスタンスが収集されていることがわかり、前述の例外が発生します。

fooメインで初期化している静的参照です。別のリモート オブジェクトがfooそのメソッドの 1 つから返されます。したがって、クライアントは最初にそのリモートオブジェクトを取得し、次にそこfooから取得し、次にメソッドを呼び出しますfoo。そのとき、上記で説明したように例外が発生します。では、なぜこのようなことが起こっているのでしょうか。

編集:これが私の主な方法です

public static void main(String[] args) throws RemoteException, AlreadyBoundException 
{

    Server server = new Server();
    Hello stub = (Hello) UnicastRemoteObject.exportObject(server, 0);

    FooImpl fi = new FooImpl();
    foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);

    Registry registry = LocateRegistry.getRegistry();
    registry.bind("Hello", stub);       
    System.out.println("Server ready!");        
}

クライアントでは、メソッドを取得helloして呼び出すと、メソッドが呼び出されてからfooメソッドが呼び出されfooます。

EDIT2:私が使用する場合

Hello stub = (Hello) UnicastRemoteObject.exportObject(new Server(), 0);

foo最初にバインドhelloしてから 、アクセスしようとすると同じ例外がスローhelloされます。これは、収集されているサーバーインスタンスであるためです。本当に奇妙なもの!

4

1 に答える 1

3

どちらのアプローチも失敗する可能性があります。変数のスコープに関しては、それらの間に実際の違いはありません。

これらの状況でより一般的に見られる問題は、 によって作成されたときのレジストリ自体LocateRegistry.createRegistry()です。これは実行していません。もしそうなら、作成されたレジストリ自体も GC できます:Registry参照を静的変数に保持する必要があります。次に、それは GC されず、スタブが GC されるのを防ぎ、スタブfooFooImplが DGC されるのを防ぎ、したがって GC されます。

あなたの場合、リモートオブジェクト参照(スタブではなくサーバー)を静的変数に保持する方がよいでしょう。

于 2012-10-05T22:35:19.657 に答える