HOWTO · Python

Python から Java を呼び出す

この記事では、複数の Java to Python ライブラリを使用して Python から Java を呼び出すいくつかの方法について説明します。

このページの内容

PythonからJavaを呼び出すには、JavaをPythonプロセス内に読み込むブリッジか、別のJavaプロセスと通信するブリッジを使います。このガイドでは、Pyjnius、Javabridge、JPype、Py4Jを取り上げます。適切な選択肢は実行環境や、JVMを組み込む必要があるか、ゲートウェイを使うかによって異なります。ランタイムを比較している場合は、以前のJythonガイドで別の方法を説明しています。日本語版のリンク先はないため、リンクは英語版を指します。

PythonからJavaを呼び出すブリッジを選ぶ

Pyjnius、Javabridge、JPypeはネイティブ連携を通じてPythonをJVMに接続します。一方、Py4Jは別々のプロセス間にゲートウェイを使います。選ぶ前に、各プロジェクトの最新のインストール手順を確認し、対応するPython、Java、OS、パッケージのバージョンを調べてください。以下の例は各APIの使い方を示すもので、この記事の環境では実行テストされていません。

Pythonだけを使う簡単なスモークテストを実行するには、次のようにします。

このセクションのコードと表示されるラベルや出力は英語のままです。

message = "Java in Python Success"
print(message)
Java in Python Success

この例で確認できるのは、Pythonがメッセージを出力できることだけです。表示される文字列「Java in Python Success」はコード内の値であり、英語のままです。Javaブリッジのテストにはなりません。以下のブリッジ別のスニペットは簡潔なAPI例です。利用するパッケージをインストールし、対応するJVMまたはゲートウェイを用意してから、実際の環境に合わせてください。

PythonからJavaを呼び出す方法:Pyjnius

PyjniusはJNIを通じてJavaクラスをPythonに公開します。JVMとコンパイラーを含むJDKをインストールし、プログラムの実行に使うPython環境にpyjniusパッケージをインストールしてください。たとえば、インストールコマンドはpip install pyjniusです。利用するプラットフォームとPython環境に対応したバージョンを選びます。

Javaのクラス名はjava.lang.Systemです。そのoutフィールドはPrintStreamインスタンスで、printlnはそのストリームのインスタンスメソッドです。この例ではjniusからautoclassをインポートし、autoclass("java.lang.System").out.println("Java in Python Success")を呼び出します。パッケージとJVMを設定すると、printlnはこの文字列を標準出力に送ります。ただし、このブリッジ呼び出しはAPIの例であり、ここでは実行テストされていません。これはSystem自体の静的なprintlnメソッドを呼び出す方法とは異なります。また、Pythonを実行するホストが互換性のあるJVMライブラリを検出できる必要があります。

PythonからJavaを呼び出す方法:Javabridge

Javabridgeを使うとPythonからJavaにアクセスでき、起動済みのJVM上でJava側のコードを実行できます。動作はJVMとクラスパスの設定に左右され、インストール時に互換性のあるネイティブビルドツールが必要になる場合があります。使用するPython環境にjavabridgeをインストールし、プロジェクトが示すプラットフォーム別の前提条件に従ってください。

ブリッジを呼び出す前にJVMを起動します。呼び出しが失敗しても後処理できるよう、finallyブロックで停止してください。最小限のAPIの形は、javabridge.start_vm(run_headless=True)で起動し、javabridge.run_script('java.lang.String.format("Hello, %s!", greetee);', dict(greetee="world"))を実行して、後処理でjavabridge.kill_vm()を呼び出すものです。プロジェクトのクラスやJARを使うスクリプトでは、それらのファイルをJVMのクラスパスに追加する必要があります。上の呼び出しではJava標準のStringクラスだけを使っています。JavabridgeはJavaコードからPythonを呼び出す使い方にも対応できるため、大きな連携処理ではどちら側が操作を担うのかを明確にしてください。

PythonからJavaを呼び出す方法:JPype

JPypeはPythonプロセス内でJVMを起動し、Python APIを通じてJavaパッケージを公開します。jpype1ディストリビューションをインストールし、Javaクラスにアクセスする前にJVMを起動してください。JVMがインストールされ、検出可能であれば、jpype.getDefaultJVMPath()で既定のJVMパスを取得できます。

呼び出しの流れは、import jpype as jp、jp.startJVM(jp.getDefaultJVMPath())、jp.java.lang.System.out.println("hello world")、jp.shutdownJVM()です。アプリケーションでは後処理の中でJVMを停止し、停止後に同じJVMを再起動しようとしないでください。長時間動作するPythonプロセスを設計する際は、JVMのライフサイクル上の制約を考慮する必要があります。JPypeはJavaオブジェクトを公開し、PythonからJavaを操作できますが、具体的な型や変換は使用するAPIによって異なります。これは独立したJavaサービスでも、性能を保証するものでもありません。

PythonからJavaを呼び出す方法:Py4J

Py4JはPythonコードをJavaのゲートウェイプロセスに接続します。Python側にpy4jパッケージをインストールし、対応するPy4JのJavaコンポーネントをJavaアプリケーションから利用できるようにしてください。ゲートウェイサーバーを別途起動してからJavaGateway()で接続します。既定の接続では、設定済みのアドレスとポートでゲートウェイが待ち受けている必要があります。

接続後は、gateway.jvmを通じてJavaのパッケージやクラスにアクセスできます。たとえば、gateway.jvm.java.lang.System.out.println("Hello World!")というAPIの形でJavaのPrintStream.printlnを呼び出します。アプリケーションクラスを生成するには、gateway.jvm.mypackage.MyClass()のように完全修飾名を使い、返されたオブジェクトのメソッドを呼び出します。このプレースホルダーは、ゲートウェイから実際に公開されているクラス名に置き換えてください。Py4JはJNIでJVMを組み込むのではなく、独自のプロトコルを使ってソケット経由で要求を送ります。用途に応じて設定すれば、JavaからPython側のオブジェクトを呼び出すコールバックにも対応します。

アプリケーションとデプロイ上の制約に合うなら、プロセス内JVMを使うPyjniusまたはJPypeを選びます。PythonとJavaを別プロセスのままにする場合や、ゲートウェイ経由で通信する場合はPy4Jを検討してください。JavaとPythonの間の実行機能やクラスパス処理が必要な連携には、Javabridgeが適しています。選択したプロジェクトのプラットフォーム対応状況とライフサイクル上の要件を確認してください。各方式は設定方法と通信モデルが異なり、ここでは普遍的な性能順位を示していません。