ErlangとJavaをつなぐ
この記事では、ErlangとJavaの連携方法を説明します。
使い道
Erlangで出来ているプログラムを使いたいが、今Erlangが分かる人がいない。
でも、Javaが分かる人はいる。こういった状況でErlang + Javaが使えるのではないでしょうか。
また、Erlangがネットワークや並行処理に強い反面、
他の言語に比べてパフォーマンスがよくないところ(演算など)があるようで、
そういった部分はJavaに担当させるのもいいでしょう。
GUIやRDB操作はJavaに任せて、分散処理はErlangに担当させるなどもありだと思います。
実際、Erlang + Javaではありませんが、
ある商用のメール配信エンジン(?)は、
メインをErlangにして、計算速度が必要な部分は
C言語で開発したとの記事を見たことがあります。
Jinterface
JavaからErlang プログラムを呼び出すための、Erlang 公式Java APIパッケージです。
APIは実際通信を行う部分とErlangデータタイプをJavaクラスとして実装した部分で構成されています。
このAPIパッケージを使えば、Erlangプログラムと連携できます。
jinterfaceのjarファイルは、${ERLANG_HOME}/lib/jinterface(又はjinterface-x.y.z)/privディレクトリ配下にOtpErlang.jarという名前で配置されています。
サンプル
受け取ったメッセージをそのまま返すエコサーバのようなErlangプログラムと、
そのエコサーバを呼び出すJavaプログラムを作成してみます。
まず、Erlangプログラムです。
Erlang 基礎ポイント7 - 分散処理 - DukeLabに出たサンプルソースと同じです。
-module(echo). -export([start/0, send/2]). start() -> register(echo, spawn(fun() -> loop() end)). send(Msg, Receiver) -> Receiver ! {self(), {server, Msg}}, receive {client, Res} -> Res end. loop() -> receive {From, {server, Msg}} -> From ! {client, string:concat("Echo response : ", Msg)}, loop() end.
このErlangプログラムをコンパイルして、実行しておきます。
今回は、VirtualBox上に動くUbuntu 12.04で実行しました。
REPL環境上でテストもしてみます。
Javaからアクセスする時、識別に必要なため、erl起動時にnameとsetcookieの指定が必要です。
nameとsetcookieはメモしておいて下さい。
$ erl -name echoserver@vpc1.com -setcookie echocookie (echoserver@vpc1.com)1> c(echo). {ok,echo} (echoserver@vpc1.com)2> echo:start(). true (echoserver@vpc1.com)3> echo:send("Hello!!", echo). % 自分自身への呼出でテスト。 "Echo response : Hello!!"
次は、Javaプログラムです。
ビルドパスにjinterfaceのjarファイル(OtpErlang.jar)を追加して下さい。
今回は、Windows 7環境とEclipseで作成しました。
こちら側のPCにもErlangがインストールされていなければなりません。
jinterfaceのjarだけでは動かないので、注意して下さい。
package dukelab.erlangjavatest; import java.io.IOException; import com.ericsson.otp.erlang.OtpErlangAtom; import com.ericsson.otp.erlang.OtpErlangDecodeException; import com.ericsson.otp.erlang.OtpErlangExit; import com.ericsson.otp.erlang.OtpErlangObject; import com.ericsson.otp.erlang.OtpErlangString; import com.ericsson.otp.erlang.OtpErlangTuple; import com.ericsson.otp.erlang.OtpMbox; import com.ericsson.otp.erlang.OtpNode; public class ErlangJavaTest { public static void main(String[] args) throws IOException, OtpErlangDecodeException, OtpErlangExit { // javanode : Javaプログラム側のホスト名です。任意で指定します。 // echocookie : Erlangプログラム側でerl実行時、指定したクッキー名と同じです。 OtpNode node = new OtpNode("javanode", "echocookie"); OtpMbox mBox = node.createMbox(); // メッセージをErlangプログラム側に送ります。 // これをErlangプログラムで表現すると、 // { echo, 'echoserver@vpc1.com' } ! { self(), {server, "Hello Erlang, I am Java."} }になります。 { OtpErlangTuple tuple = createTuple( mBox.self(), createTuple( new OtpErlangAtom("server"), new OtpErlangString("Hello Erlang, I am Java.") ) ); // echo : Erlangプログラム側で登録したプロセス名です(register(echo, spawn(fun() -> loop() end)))。 // echoserver@vpc1.com : Erlangプログラム側でerl実行時、指定したホスト名です。 mBox.send("echo", "echoserver@vpc1.com", tuple); } // 応答を受け取ります。 { OtpErlangObject result = mBox.receive(); OtpErlangTuple tuple = (OtpErlangTuple) result; OtpErlangAtom atom = (OtpErlangAtom) tuple.elementAt(0); OtpErlangString str = (OtpErlangString) tuple.elementAt(1); System.out.println("Response from Erlang : " + str); } } private static OtpErlangTuple createTuple(OtpErlangObject... msg) { return new OtpErlangTuple(msg); } }
その後、JavaプログラムのPCにあるhostsファイルに、
先ほどのErlang実行時にnameに指定したドメイン名とIPアドレス(Erlangを実行したPC)の対応を追加します。
例えば、以下のようにです。
192.168.56.101 vpc1.com
さあ、Javaプログラムを実行してみましょう。
Response from Erlang : "Echo response : Hello Erlang, I am Java."
できました!
整理
jinterfaceを使うと、Erlangプログラムと同じく動作するプログラムを
Javaで作成することができます。
サーバ役割のプログラムもクライアント役割のプログラムもできます。
いくつかのErlang機能に対応するJavaクラスを以下に並べます。
- Erlang起動(Erlangの仮想マシン) : OtpNode
- メッセージをやりとりする(Erlangでの!やreceiveなど) : OtpMbox
- タプル : OtpErlangTuple
- 文字列 : OtpErlangString
- アトム : OtpErlangAtom
この記事が理解できたら、後は、参考資料を読みながら、掘り下げていけばいいと思います。