Java
 Computer >> コンピューター >  >> プログラミング >> Java

JavaのRMIでリモートメソッドを介してデータを送信する方法を徹底解説


RMI(Remote Method Invocation)とは?

RMI(Remote Method Invocation、リモートメソッド呼び出し)とは、あるシステム(JVM)上に存在するオブジェクトが、別のJVM上で動作しているオブジェクトにアクセスしたり、そのメソッドを呼び出したりできるようにするJavaの仕組みです。

RMIは分散アプリケーションを構築するための技術で、Javaプログラム同士のリモート通信を実現します。java.rmiパッケージとして標準提供されており、ネットワーク越しでもあたかもローカルのメソッドを呼び出すかのような感覚でコードを書けるのが大きな特徴です。

本記事では、RMIを使ってリモートメソッド経由でデータを送信するJavaアプリケーションを、以下の6つのステップで作成していきます。

ステップ1:リモートインターフェースを定義する

リモートインターフェースは、特定のリモートオブジェクトが提供する全メソッドのシグネチャを宣言するものです。クライアントはこのインターフェースを通じてサーバー側のオブジェクトとやり取りします。

具体的には、Javaにあらかじめ用意されているjava.rmi.Remoteインターフェースを継承したインターフェースを作成します。また、リモート呼び出し時に発生しうる通信エラーに備え、各メソッドはRemoteExceptionをスローするよう宣言します。

サンプルコード

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote {
    void printMsg() throws RemoteException;
}

ステップ2:実装クラス(リモートオブジェクト)を作成する

次に、ステップ1で定義したリモートインターフェースを実装したクラスを作成します。実装クラスを独立したファイルとして用意してもよいですし、サーバープログラム自身に直接インターフェースを実装させることも可能です。

重要なのは、リモートインターフェースで宣言したすべての抽象メソッドに具体的な処理を実装することです。

サンプルコード

public class ImplExample implements Hello {
    public void printMsg() {
        System.out.println("This is an example RMI program");
    }
}

ステップ3:サーバープログラムを作成する

RMIサーバープログラムは、リモートインターフェースを実装するか、実装クラスを継承して作成します。サーバーの主な役割は次の2つです。

  • リモートオブジェクトのインスタンスを生成し、UnicastRemoteObject.exportObject()でエクスポートしてスタブ(クライアント側の代理オブジェクト)を取得する
  • そのスタブを名前とともにRMIレジストリにバインド(登録)する

サンプルコード

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class Server extends ImplExample {
    public Server() {}

    public static void main(String args[]) {
        try {
            ImplExample obj = new ImplExample();
            Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.bind("Hello", stub);
            System.err.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

ステップ4:クライアントプログラムを作成する

クライアント側では、RMIレジストリから名前を指定してリモートオブジェクト(スタブ)を検索(lookup)し、取得したスタブを通じて目的のメソッドを呼び出します。通常のローカルメソッド呼び出しとほぼ同じ感覚で記述できる点がRMIの魅力です。

サンプルコード

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
    private Client() {}

    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry(null);
            Hello stub = (Hello) registry.lookup("Hello");
            stub.printMsg();
        } catch (Exception e) {
            System.err.println("Client exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

ステップ5:アプリケーションをコンパイルする

以下の順番ですべてのソースファイルをコンパイルします。

  • リモートインターフェース(Hello.java)
  • 実装クラス(ImplExample.java)
  • サーバープログラム(Server.java)
  • クライアントプログラム(Client.java)

なお、Java 5以降ではスタブ生成のためのrmicコマンドは不要となり、コンパイル時に動的スタブが自動的に生成されるようになっています。

ステップ6:アプリケーションを実行する

まず、以下のコマンドでRMIレジストリを起動します。

start rmiregistry

Windows環境では上記コマンドにより、別ウィンドウでRMIレジストリが起動します。LinuxやmacOSの場合は、ターミナルでrmiregistry &と入力してバックグラウンドで起動してください。

続いて、サーバーのクラスファイルを実行します。正常に起動すると、コンソールに「Server ready」と表示されます。

java Server
Server ready

最後に、クライアントのクラスファイルを実行します。

java Client

動作確認: クライアントを起動すると、リモートメソッドprintMsg()がサーバー側で実行され、サーバーのコンソールに次の出力が表示されます。

This is an example RMI program

まとめ

RMIを使えば、ネットワーク上の別JVMで動作するオブジェクトのメソッドを、まるでローカルのメソッドのように呼び出すことができます。手順は「①リモートインターフェースの定義 → ②実装クラスの作成 → ③サーバープログラムの作成 → ④クライアントプログラムの作成 → ⑤コンパイル → ⑥RMIレジストリの起動と実行」の6ステップです。

また、引数や戻り値としてオブジェクトを送受信したい場合は、そのクラスにjava.io.Serializableを実装しておく必要がある点に注意しましょう。分散システムや社内ツールの開発などで、ぜひRMIを活用してみてください。

  1. JavaのJListでアイテム選択時に値を表示する方法

    JListはJComponentクラスのサブクラスであり、ユーザーがリストから単一または複数の項目を選択できるようにするSwingコンポーネントです。JListはListSelectionListenerインターフェースを利用でき、このインターフェースには抽象メソッドvalueChanged()が1つだけ定義されています。JListで項目が選択されたときにその値を表示するには、MouseListenerインターフェースを実装するか、MouseAdapterクラスを継承します。そして、MouseEventクラスのgetClickCount()メソッドを使ってシングルクリック(getClickCo

  2. JavaでJPanelのpaintComponent()メソッドを実装する方法をわかりやすく解説

    JPanelはJavaにおける軽量コンテナであり、それ自体は不可視(インビジブル)なコンポーネントとして扱われます。デフォルトのレイアウトにはFlowLayoutが採用されています。JPanelを生成した後は、Containerクラスから継承されたadd()メソッドを呼び出すことで、ボタンやラベルなどの他のコンポーネントをJPanelオブジェクトに自由に追加できます。 paintComponent()メソッドとは このメソッドは、単なる背景色の描画にとどまらず、JPanel上に独自の図形や画像などを描画したい場合に必要となります。paintComponent()メソッドはすでにJPanelクラ