[Oracle] Java ストアドプロシージャで DLL を使用する際の注意点 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

Windows 版の Oracle で、Java ストアドプロシージャから外部 DLL をロードして使用したい場合、注意すべき点が3点あります。

1つ目は DLL の配置場所、2つ目はセキュリティ、そして3つ目は...です。

まず、配置場所については、java.library.path で示されるパスでなければなりません。


java.library.path が実際にどこを示しているかを確認するには、Java プログラムの中で、

System.out.println(System.getProperty("java.library.path"));

とでもすれば確認できますが、Windows版の場合、環境変数 PATH で指定されたパスということになります。

ちなみに java.library.path に配置されていない場合は、以下のようなエラーが発生します。

(hoge.dllをロードしようとした場合)

java.lang.UnsatisfiedLinkError: no hoge in java.library.path
セキュリティについては、Oracle Database Java 開発者ガイド(10g)に以下のような記述があります。

注意: SYS には、Oracle に付属するライブラリをロードするためのパーミッションが付与されています。 ただし、データベースにC をロードすることはセキュアでないため、OracleJVM では他のユーザーによるライブラリのロードはサポートされていません。


要するに、セキュリティ上問題があるため、SYS 以外のユーザーは DLL をロードできないということのようです。

ちなみに、SYS 以外のユーザーが DLL をロードしようとすると以下のようなエラーが発生します。

(hoge.dllをロードしようとした場合)

java.security.AccessControlException: the Permission (java.lang.RuntimePermission loadLibrary.hoge) has not been granted to SCOTT. The PL/SQL to grant this is dbms_java.grant_permission( 'SCOTT', 'SYS:java.lang.RuntimePermission', 'loadLibrary.hoge', '' )

このメッセージをそのまま解釈すると、DBMS_JAVA.GRANT_PERMISSION を実行して"loadLibrary"権限を付与してやればロードできるようにも思えますが、実際に実行してみると、

CALL dbms_java.grant_permission( 
  'SCOTT', 'SYS:java.lang.RuntimePermission', 'loadLibrary.hoge', '' 
);
以下のようなエラーが発生します。

ORA-29532: 不明なJava例外でJavaコールが終了しました: java.lang.SecurityException: policy table update SYS:java.lang.RuntimePermission, loadLibrary.hoge

ということで、DLL をロードする Java ストアドプロシージャについては、SYS スキーマに作成しなければならないようです。

ただ、SYS ユーザーで実行しなければならない...というわけではありません。

実行ユーザーに対して SYS スキーマに作成したJava ストアドプロシージャのコールスペックの実行権限を与えてやればそれでいいようです。

例えば、SCOTT ユーザーに対して "hoge.dll" をロードする Java ストアドプロシージャ のコールスペック "SYS.HOGE_PROC" の実行権限を与える場合は以下の分を実行します。

GRANT EXECUTE ON SYS.HOGE_PROC TO SCOTT;
なんだか、ちょっと不便で不恰好だが、このようにするしかないようです^^;


さて...これだけ注意すれば使えそうなものですが、Oracle Database Java 開発者ガイド(10g)にさらにこんな注意書きがありまs。

Java ネイティブ・インタフェース(JNI)は、Java ネイティブ・メソッドの作成、および Java 仮想マシンのネイティブ・アプリケーションへの埋込みを行うための標準プログラミング・インタフェースです。JNI の主要目的は、プラットフォーム固有のネイティブ・ライブラリを使用するJava アプリケーションのバイナリ互換性を提供することです。 Oracle では、Oracle Database のJava アプリケーションにおけるJNI の使用はサポートされていません。JNI を使用する場合、アプリケーションが100% Pure Java ではないため、ネイティブ・メソッドをプラットフォーム間で移植する必要があります。ネイティブ・メソッドを使用すると、サーバーのクラッシュ、セキュリティ違反およびデータ破損などの問題が発生する可能性があります。

実際に私があるDLLを使ってみたところ、特定のケースでうまく動作しないという現象があり、調べてみるとこういうことをしれ~っと書いていたのですが、要は問題なく動くこともあるかもしれないが、動かなくても保証はできないということのようです。

どうしても Oracle の Java から DLL を使いたいという場合はそのことを十分留意して使わなくてはなりません。



【関連エントリ】
[Oracle] Java ストアドプロシージャの利用法 2004/07/30
[Oracle] Java ストアドプロシージャで日本語ファイル名が扱えない 2004/12/27
[Oracle] loadjava ユーティリティが落ちる? 2006/06/29
[Oracle] Java ストアドプロシージャで Java クラス・ライブラリを使用する 2006/07/05
[Oracle] Java ストアドプロシージャで DLL を使用する際の注意点 2006/07/11