2

分散処理ツールの範囲内での RMI レジストリの作成と取得に関する問題があります。まず、私の環境を簡単に説明します。

環境
永続的に実行されるバックグラウンド Java プロセスが必要です。ソフトウェアのインスタンス (同じ物理マシン内) は、いくつかの操作を実行するためにそのプロセスと通信する必要があります。同じ物理マシン上で異なる JVM と通信するために数か月前に見つけたソリューションは、Java RMI でした。そこで、バックグラウンド プロセスを起動し、そこからレジストリを作成します。

    CAEATServiceManagerInterface smi = (CAEATServiceManagerInterface)UnicastRemoteObject.exportObject(csm, 0);
    Registry registry = LocateRegistry.createRegistry(8090);            
    registry.rebind("ServiceManager", smi);

注: csmは、エクスポートされるリモート オブジェクトです。セキュリティ ポリシーは適切にインストールされており (すべてのユーザーに対して AllPermission)、RMISecurityManager も同様にインストールされています。

今のところ、私のメイン プログラムのインスタンスは、いつでもレジストリを検索し、リモート オブジェクトを取得できます。

    Registry registry = LocateRegistry.getRegistry(8090);
    smi = (CAEATServiceManagerInterface)registry.lookup("ServiceManager");

問題
この問題は、プログラム (レジストリを取得するメイン プログラムとレジストリを作成するバックグラウンド プログラムの両方) が jar ファイル内から実行されるときに発生します。それらが Eclipse から実行された場合、すべて正常に動作します。コマンドラインから直接実行してもOKです。しかし、それらが配布用に自動実行可能な jar ファイルにパックされている場合、バックグラウンド プロセスによってレジストリが正常に作成されているように見えますが、メイン プログラムがそれをルックアップしようとすると、次のようになります。

java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.io.EOFException
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at sener.caeat.autoejecutable.PublicadorStandalone.getServiceManagerInterface(PublicadorStandalone.java:170)
    at sener.caeat.autoejecutable.PublicadorStandalone.publicarEsquema(PublicadorStandalone.java:319)    
    at sener.caeat.autoejecutable.CargadorStandalone.mostrarDialogoOpcionesPublicacion(CargadorStandalone.java:415)
    at sener.caeat.autoejecutable.ExtractorJars.main(ExtractorJars.java:32)
Caused by: java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1296)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    at sun.rmi.server.MarshalInputStream.readLocation(MarshalInputStream.java:285)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:228)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    ... 5 more

私のクラスは忘れてください。私が理解していないのは EOFException です... プログラムが jar 内から実行されたときにのみ起動されるのはなぜですか?

追加データ: バックグラウンド プログラムが jar ファイル内から起動され、レジストリをルックアップするメイン プログラムが Eclipse から起動された場合、問題は依然として存在します。

前もって感謝します。

4

2 に答える 2

0

ついに解決策を見つけました。これは RMI とは直接関係がありませんでしたが、私のプログラムが自動実行可能な jar ファイルにパックされていたことに関係していました。

私のサブプロセスの特徴の 1 つは、カスタム RMI ClassLoader を使用してカスタム リモート クラス解決に関連するものを処理することです。これは、次のステートメントによって実現されます。

System.setProperty("java.rmi.server.RMIClassLoaderSpi","<My_custom_RMI_ClassLoader>");

注意: これは jar ファイル内から実行されます。クラス「My_custom_RMI_ClassLoader」は jar 内にあるため、スローされた例外は ClassNotFoundException ではありませんでした。しかし、ここで私の間違いが発生します。このクラスには内部クラス (名前が $innerClass.class で終わるクラスの 1 つ) があります。そして、その .class ファイルは JAR ファイル内にパックされていませんでした。これが、プロキシ クラスが解決されたときに EOFException が発生した理由だと思います。

ありがとうございます。問題は思ったより微妙でした。

于 2012-09-27T00:01:17.193 に答える
0

これは通常、相手側の SocketPermissions に関連する SecurityExceptions が原因で発生し、着信接続が途中で閉じられます。そのログを見てください。

于 2012-09-26T02:05:19.060 に答える