.NET から Java のロギングパッケージを呼び出す — JNBridgePro デモガイド
本文は日本語です。画面内の表示、操作するメニュー名、ファイル名、コードは英語版のまま掲載しています。
はじめに
このガイドでは、JNBridgePro を使い、C# から Java クラスを呼び出す .NET コンソールアプリケーションを作成します。Apache の Java ロギングパッケージ log4j と、既存の Java クラス loggerDemo.JavaClass に対応する .NET プロキシを生成します。JavaClass の doIt() メソッドは、log4j を通じてメッセージを記録します。.NET クラスからも同じプロキシを使ってログを記録することで、Java 側と .NET 側のメッセージを単一の log4j 出力にまとめ、1 つの設定でロギングを制御できます。これは、.NET コードを既存の Java コードベースと連携させる際によく求められる構成です。
JNBProxy のデモプロジェクトのエクスポート機能により、.NET 側のセットアップは自動で行われます。生成したプロキシアセンブリと JNBridgePro ランタイムを参照する Visual Studio ソリューションが作成され、共有メモリ通信と TCP 通信の両方の設定ファイルが追加されます。Java 側のコンポーネントもコピーされ、1 つのコマンドでデモをビルドして実行するスクリプトが生成されるため、プロジェクトを手動で構成する必要はありません。
必要なもの
- Java JDK、および .NET Framework 4.8 ターゲティングパックを備えた .NET SDK。
- JNBridgePro v12.1 — jnbridge.com からダウンロードしてインストールしてください。このデモは無料の評価ライセンスで実行できます。
- デモファイル — log4j.jar、log4j-core.jar、および JavaClass.class を含む loggerDemo クラスフォルダー。JNBridgePro とともにインストールされる demos\tutorials\logDemo.zip に含まれています。このガイドでは C:\NewGui\LogDemo に展開します。
log4j のファイルはあくまで一例です。以下の手順は、ご自身のコードにも適用できます。クラスパスの JAR ファイルとクラスフォルダーをご自身のものに置き換え、利用したいクラスを公開対象に選択してください。JNBProxy は同じ手順でプロキシを生成し、それを利用する実行可能なひな形のプロジェクトをエクスポートします。
プロキシの生成
JNBProxy を起動し、Create new .NET → Java project を選択します(図 1)。メインウィンドウ(図 2)では、番号付きの 4 つのステップに沿ってプロキシを生成します。クラスパスの設定、クラスの Environment への読み込み、公開するクラスの選択、プロキシアセンブリのビルドという流れです。進捗や診断メッセージは、下部の Output ペインに表示されます。


1クラスパスを設定する
Windows エクスプローラーから log4j.jar と log4j-core.jar をドロップ領域にドラッグします。または、Edit classpath… をクリックして追加します。次に、loggerDemo クラスフォルダーを含むフォルダー(この例では C:\NewGui\LogDemo)も同様に追加します。追加した項目は、Classpath パネルの上部にチップとして表示されます(図 3、4)。


Edit Class Path ダイアログ(図 5)には、各項目のフルパスが表示されます。このダイアログでは、Add… でパスを指定して項目を追加したり、× ボタンで削除したりすることもできます。

2クラスを Environment に読み込む
Add Classes from JAR を開き、log4j.jar を選択します(図 6)。log4j-core.jar についても同じ操作を行います。単一のクラス JavaClass を読み込むには、Add Classes from Classpath を使用します。検索欄に入力して loggerDemo.JavaClass にチェックを入れ、Include supporting classes をオンのままにして OK をクリックします(図 7)。クラスが Environment ツリーに読み込まれる様子は、Output ペインで確認できます。


3公開するクラスを選択する
今回は、これらすべてのクラスのプロキシを生成します。Environment パネルの Select all にチェックを入れ、Add+ をクリックします(図 8)。チェックしたクラスと、それらに必要な関連クラスがすべて Exposed proxies ペインに追加されます(図 9)。


4プロキシアセンブリをビルドする
Build をクリックし、生成したプロキシを格納するアセンブリの名前と保存場所を指定します。この例では LoggerDemoProxy.dll とします。生成には 1〜2 分かかり、完了すると Output ペインに BUILD COMPLETED と表示されます。
デモプロジェクトのエクスポート
次に、JNBProxy を使って、生成したプロキシを利用する実行可能な .NET プロジェクト一式を作成します。Exposed proxies パネルの歯車メニューから Export demo project… を選択し(図 10)、先ほどビルドしたプロキシ DLL を指定します。プロジェクトの名前、種類、保存場所を設定し、Export をクリックします(図 11)。この例では、プロジェクト名を LoggerDemo、種類を .NET Framework 4.8 (Windows)、作成先を C:\NewGui とします。Windows または Linux 向けの .NET 8 プロジェクトをエクスポートすることもできます。
注意:プロジェクト名は、プロキシアセンブリとは異なる名前にしてください。たとえば LoggerDemoProxy.dll を参照するプロジェクトを LoggerDemoProxy と名付けると、プロジェクト自身の出力アセンブリとプロキシアセンブリの名前が衝突し、実行時にデモが失敗します。この例では、プロキシを LoggerDemoProxy.dll、プロジェクトを LoggerDemo としています。


エクスポート先のフォルダー(図 12)には、デモに必要なファイルがそろっています。
- LoggerDemo.sln
- LoggerDemo\ — LoggerDemoProxy.dll と JNBShare.dll を参照する、SDK スタイルの C# コンソールプロジェクトです。ビルド時には JNBridge のネイティブ DLL がコピーされます。共有メモリ用の App.config と TCP 用の App.tcp.config の両方が含まれています。
- Java Side\ — jnbcore.jar と bcel(JNBridge の Java 側ランタイム)、クラスパスに含まれる JAR のコピー、Java 側のプロパティファイル、任意で利用するクラスのホワイトリスト、および TCP モードで Java 側を手動起動するスクリプトが含まれています。
- env.bat — 実行スクリプトで使用する Java の場所を指定します。
- buildAndRunSharedMem.bat / buildAndRunTCP.bat — 各通信モードでビルドと実行をまとめて行うスクリプトです。
- ReadMe.md — プロジェクトの構成を説明しています。

各ファイルの役割、共有メモリブリッジの設定方法、および同じ構成をご自身のアプリケーションに適用する方法は、ナレッジベースの記事 Call Java from .NET Project: Anatomy of a Shared Memory Bridge(英語)で説明しています。
デモの実行
1env.bat に JVM の場所を設定する
env.bat(図 13)を開き、JAVA_HOME に JDK のルートディレクトリを設定します。共有メモリモードで使用する 64 ビット版 jvm.dll の場所を示す JVM_DLL_64 は、既定では JAVA_HOME から設定されます。
JNBProxy 自体に設定されていた jvm.dll のパスは、LoggerDemo\App.config の jvm64 属性に記録されているため、そこからコピーすることもできます。

2ブリッジの動作を確認する
buildAndRunSharedMem.bat をダブルクリックします。プロジェクトがビルドされ、env.bat の JVM パスを反映した共有メモリ用の設定ファイルが実行ファイルと同じ場所に書き込まれ、プログラムが実行されます。エクスポート直後の Program.cs は、すべてのプロキシアセンブリに含まれる java.lang.Object を使って、ブリッジ経由の呼び出しと戻り値の受け取りを確認する最小限のコードです。Java オブジェクトのハッシュ値を含む文字列が表示されれば、ブリッジが動作していることを確認できます(図 14)。
ClassNotFoundException または NoClassDefFoundError が発生して実行に失敗する場合は、JVM がクラスパス上のクラスを読み込めていません。よくある原因は、JAR やクラスフォルダーの移動、またはそれらに対する読み取り権限の不足です。原因と対処方法は、共有メモリブリッジの構成を解説したナレッジベース記事(英語)の「Handling ClassNotFoundException and NoClassDefFoundError」を参照してください。

3デモコードを追加する
LoggerDemo\Program.cs の内容を、次のコードに置き換えます。
using System; using org.apache.log4j; using java.lang; using loggerDemo; namespace LoggerDemo { class Program { static Category cat = Category.getInstance("com.jnbridge.demos.logger.LoggerDemo"); /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { BasicConfigurator.configure(); cat.info(new JavaString("Entering application")); DotNetClass dotNetClass = new DotNetClass(); JavaClass javaClass = new JavaClass(); for (int i = 0; i < 5; i++) { dotNetClass.f(); javaClass.doIt(); } cat.info(new JavaString("Exiting application")); } } public class DotNetClass { static Category cat = Category.getInstance("com.jnbridge.demos.logger.DotNetClass"); public void f() { cat.debug(new JavaString("Logged from .NET")); } } }
コードのポイントは次のとおりです。
- プロキシの名前空間は Java のパッケージ名と一致します。org.apache.log4j、java.lang、loggerDemo をインポートすると、Category、BasicConfigurator、JavaClass を Java と同様に利用できます。
- info() と debug() に渡す文字列は、java.lang.JavaString でラップします。これらのメソッドは java.lang.Object を引数に取ります。.NET の string は java.lang.Object ではありませんが、JavaString は java.lang.Object を継承しています。
- ソリューションを Visual Studio で開くと、.NET クラスと同じように、Java プロキシのメソッド呼び出しにも IntelliSense の入力補完を利用できます。
4実行する
buildAndRunSharedMem.bat をもう一度実行します。今度は、.NET 側と Java 側で生成されたログメッセージが、単一の log4j 出力に混在して表示されます(図 15)。

共有メモリモードでは、Java 側は .NET プロセス内で動作します。最初のプロキシ呼び出しの前に JVM が自動的に読み込まれるため、Java 側を明示的に起動する必要はありません。共有メモリは最も高速な通信方式であり、このデモを実行する最も簡単な方法です。
TCP/binary 通信の利用
エクスポートしたプロジェクトでは、Java 側を別プロセスで実行し、TCP/binary で通信することもできます。違いは、LoggerDemo プロジェクトフォルダー内の 2 つの設定ファイルに表れています。共有メモリ用の App.config では、JVM が .NET プロセス内で動作するため、JVM の場所と Java のクラスパスを指定します。
<dotNetToJavaConfig scheme="sharedmem" jvm64="C:\Program Files\Java\jdk-11\bin\server\jvm.dll" jvm32="" jnbcore="jnbcore.jar" bcel="bcel-6.10.0.jar" classpath=".;log4j.jar;log4j-core.jar;C:\NewGui\LogDemo" />
TCP 用の App.tcp.config では、Java 側の接続先を指定します。
<dotNetToJavaConfig scheme="jtcp" host="localhost" port="8085" useSSL="false" />
TCP モードでは、クラスパスなどの Java 側の設定を、Java 側の起動時に指定します。Java 側は jnbcore.jar をクラスパスに含め、jnbcore_tcp_no_security.properties を読み込んで起動し、ポート 8085 で接続を待ち受けます。Java Side フォルダーの「start Java side.bat」を参照してください。buildAndRunTCP.bat は、ビルド、App.tcp.config への切り替え、Java 側の起動、デモの実行、実行後の Java 側の終了という一連の処理を自動化します。
TCP 通信では、Java 側で呼び出しを許可するクラスを制限することもできます。クラスのホワイトリストは、classWhiteList.txt と javaSide.useClassWhiteList / javaSide.classWhiteListFile プロパティで設定します。また、SSL を使って通信を保護できます。どちらも ユーザーガイド(英語)を参照してください。
まとめ
このデモでは、3 つの段階で Java と .NET のロギングを統合しました。まず JNBProxy で log4j のクラスと loggerDemo.JavaClass に対応する .NET プロキシを生成し、次にデモプロジェクトのエクスポート機能で設定済みのソリューションを作成しました。最後に Program.cs にデモコードを追加し、1 つのスクリプトで共有メモリまたは TCP を使って実行しました。Java 側と .NET 側のメッセージは、1 つの設定で管理される単一の log4j 出力に送られます。このように Java と .NET を相互運用できるようにすることで、JNBridgePro は、.NET プラットフォームを利用しながら既存の Java コードを活かすことを支援します。同じ 3 つの手順は、C# から利用したい Java ライブラリやクラス(英語)にも適用できます。また、関連する Java → .NET のデモガイド(英語)で示すように、逆方向の連携にも利用できます。















