2.5 Javaクラス・メソッドの実行準備
- Javaソース・コードをいつコンパイルするかを決定します。
- データベース内のJavaクラスの位置の特定に、デフォルトのリゾルバを使用するか、別のリゾルバを使用するかを決定します。
- クラスをデータベースにロードします。クラスにデフォルトのリゾルバを使用しない場合は、ロード・コマンドで別のリゾルバを指定してください。
- クラスまたはメソッドを公開します。
2.5.1 Javaクラスのコンパイル
Javaソース・コードのコンパイルは、次のいずれかの方法で実行できます。
関連トピック
2.5.1.1 javacによるソースのコンパイル
次の例に示すように、従来のJavaコンパイラを使用してJavaソース・コードをコンパイルできます。
javac <file_name>.java
コンパイルが終了した後は、ソースではなく、コンパイル済バイナリをデータベースにロードします。通常は、データベースでデバッグするよりも、各自のシステムでJavaコードをデバッグする方が簡単なため、これは便利なオプションです。
2.5.1.3 実行時におけるソースのコンパイル
次のように、-resolve
オプションを指定せずにデータベースにJavaソースをロードするとします。
loadjava <file_name>.java
この場合、実行時にクラスが必要になったときに、ソースが自動的にコンパイルされます。ソース・ファイルは、ソース・スキーマ・オブジェクトにロードされます。Oracle Databaseによって、すべてのコンパイル・エラーがloadjava
ツールのログ・ファイルとUSER_ERRORS
ビューに書き込まれます。
2.5.1.4 コンパイラ・オプションの指定
コンパイラ・オプションを指定するには、次の方法があります。
2.5.1.4.1 デフォルトのコンパイラ・オプションの指定
コンパイル対象のソース・スキーマ・オブジェクトに、JAVA$OPTIONS
表のエントリもコマンドラインのオプション値も指定されていない場合は、次のデフォルト値が使用されます。
-
encoding=System.getProperty("file.encoding");
-
online=true
このオプションは、SQLJ構文が含まれているJavaソースにのみ適用されます。
-
debug=true
このオプションは、次のように指定した場合と同じです。
javac -g
2.5.1.4.2 コマンドラインでのコンパイラ・オプションの指定
loadjava
ツールにencoding
コンパイラ・オプションを指定すると、.java
ファイルのエンコーディングが識別されます。このオプションは、JAVA$OPTIONS
表内の一致する値をすべてオーバーライドします。この値は、次のように指定した場合と同じです。
javac -encoding
このオプションはソース・ファイルのロード時のみ有効です。
2.5.1.4.3 データベース表に指定されるコンパイラ・オプションの指定
JAVA$OPTIONS
表の各エントリには、オプションの設定を適用するソース・スキーマ・オブジェクトの名前が指定されています。複数行を使用すると、ソース・スキーマ・オブジェクトごとに異なるオプションを設定できます。
次のプロシージャとファンクションを使用することで、JAVA$OPTIONS
表のエントリを設定できます。これらのプロシージャとファンクションは、データベース・パッケージDBMS_JAVA
に定義されています。
PROCEDURE set_compiler_option(name VARCHAR2, option VARCHAR2, value VARCHAR2); FUNCTION get_compiler_option(name VARCHAR2, option VARCHAR2) RETURNS VARCHAR2; PROCEDURE reset_compiler_option(name VARCHAR2, option VARCHAR2);
2.5.1.4.4 データベース表に指定されるコンパイラ・オプションの指定の詳細
次の表に、前の項で説明したメソッドのパラメータを示します。
表2-2 nameパラメータとoptionパラメータの定義
パラメータ | 説明 |
---|---|
name |
Javaパッケージ名、完全修飾されたクラス名または空の文字列が入ります。コンパイラによって、Javaソース・スキーマ・オブジェクトのコンパイルに使用するオプションが |
option |
|
最初、スキーマにはJAVA$OPTIONS
表はありません。JAVA$OPTIONS
表を作成するには、DBMS_JAVA
パッケージのjava.set_compiler_option
プロシージャを使用して値を設定します。このプロシージャは、表が存在しない場合に表を作成します。パラメータは一重引用符で囲みます。次に例を示します。
SQL> execute dbms_java.set_compiler_option('x.y', 'online', 'false');
次の表は、JAVA$OPTIONS
データベース表のサンプルです。パターン一致規則は、表エントリに対してできるかぎり多くのスキーマ名を一致させるための規則です。パターン一致の名前解決度が高いスキーマ名がエントリとして適用されます。この表には、encoding
オプションのエントリがないため、コンパイラはデフォルトまたはコマンドラインで指定された値を使用します。この表のonline
オプションは、次のようにスキーマ・オブジェクト名に対応付けられます。
-
名前
a.b.c.d
は、a.b.c.d
で始まるクラス名およびパッケージ名に一致します。このパッケージとクラスは、online=true
でコンパイルされます。 -
名前
a.b
は、a.b
で始まるクラス名およびパッケージ名に一致します。名前a.b
は、a.b.c.d
とは一致しません。このパッケージとクラスは、online=false
でコンパイルされます。 -
その他のパッケージとクラスは空文字列のエントリに一致し、
online=true
でコンパイルされます。
表2-3 JAVA$OPTIONS表の例
名前 | オプション | 値 | 一致例 |
---|---|---|---|
a.b.c.d |
|
|
|
a.b |
|
|
|
空文字列 |
|
|
|
2.5.1.5 ソース・プログラムの自動的な再コンパイル
Oracle Databaseには、依存関係管理および自動作成機能が用意されています。これらの機能は、ソース・プログラムまたはバイナリ・プログラムが変更されると、これらのプログラムに依存しているソース・プログラムを透過的に再コンパイルします。次に例を示します。
public class A { B b; public void assignB() { b = new B() } } public class B { C c; public void assignC() { c = new C() } } public class C { A a; public void assignA() { a = new A() } }
システムは詳細なクラス・レベルで依存関係を追跡します。この例では、A
がB
のインスタンスを保持し、B
がC
のインスタンスを保持し、C
がA
のインスタンスを保持しているため、クラスA
、B
およびC
が相互に依存しています。クラスA
に新しいフィールドを追加して、このクラスの定義を変更すると、Oracle Databaseの依存関係メカニズムによって、クラスB
とC
が無効になったことを示すフラグが設定されます。これらのクラスを次に使用する前に、Oracle Databaseは必要に応じて、これらのクラスを解決して、再コンパイルを試みます。クラスは、ソース・ファイルがサーバーにある場合にのみ再コンパイルされます。
この依存性のあるシステムによって、クラス間の依存関係がOracle Databaseで管理され、解決と再コンパイルが自動的に実行されます。開発作業中に問題を早期に特定する必要がある場合にのみ、コンパイルと解決を強制的に実行する必要があります。loadjava
ツールには、依存関係管理機能を利用しない場合に、コンパイルと解決を強制的に実行する機能もあります。
2.5.2 クラス依存関係の解決の概要
Javaクラスの多くには、他のクラスへの参照が含まれており、これによって、コードの再利用が可能になります。従来のJVMは、CLASSPATH
で指定されたディレクトリ内で.class
、.zip
および.jar
ファイルを検索します。一方、Oracle JVMはデータベース・スキーマでクラス・オブジェクトを検索します。Oracle Databaseでは、すべてのJavaクラスがデータベースにロードされるため、あるJavaクラスが依存しているクラスをデータベース内で検索するには、検索場所を指定する必要があります。
データベースにロードされるすべてのクラスは、クラス・スキーマ・オブジェクトと呼ばれ、特定のスキーマにロードされます。java.lang.*
など、事前に定義されているJavaのApplication Programming Interface(API)はすべて、PUBLIC
スキーマにロードされます。あるクラスが、事前に定義した他のクラスに依存している場合は、すべてのクラスをスキーマにロードすることになります。たとえば、スキーマがHR
である場合、データベース・リゾルバは、PUBLIC
スキーマを検索する前にHR
スキーマを検索します。検索するスキーマのリストはリゾルバ仕様と呼ばれます。リゾルバ仕様は各クラスごとに定義されます。CLASSPATH
がすべてのクラスに対してグローバルな、従来のJVMとは対照的です。
クラス間の依存関係を検索および解決する場合、リゾルバは、相互に依存するすべてのクラスを検出したかどうかによって、各クラスに有効または無効のマークを付けます。ロードしたクラスに、適切なスキーマに存在しないクラスへの参照がある場合、そのクラスは無効としてリストされます。実行時に解決できない場合は、ClassNotFound
例外が生成されます。また、クラスのツリーが大きすぎると、データベース・リソースが不足するため、実行時に解決できないことがあります。
ノート:
Javaコンパイラと同様に、loadjava
ツールはクラスへの参照を解決しますが、リソースへの参照は解決しません。クラスに必要なリソース・ファイルを正しくロードする必要があります。
クラス内の各クラス間参照の場合、リゾルバは、参照を満たす有効なクラス・スキーマ・オブジェクトについて、リゾルバ仕様に指定されているスキーマを検索します。すべての参照が解決されると、リゾルバによりこのクラスは「有効」とマークされます。解決処理が行われていないクラス、または正常に解決できなかったクラスは「無効」とマークされます。無効にされたスキーマ・オブジェクトに依存するクラスも無効とマークされます。
依存クラスを簡単に検索できるように、Oracle Databaseには、定義者のスキーマを検索してからPUBLIC
スキーマを検索するデフォルトのリゾルバとリゾルバ仕様が用意されています。これによって、データベースにロードされたほとんどのクラスを検索できます。ただし、各自またはPUBLIC
以外のスキーマにロードされたクラスにアクセスする場合は、独自にリゾルバ仕様を定義する必要があります。
次の方法でクラスを解決できます。
-
定義者のスキーマと
PUBLIC
を検索するデフォルト・リゾルバを使用してロードします。loadjava -resolve
-
独自のリゾルバ仕様定義を使用してロードします。
loadjava-resolve -resolver "((* HR)(* OTHER)(* PUBLIC))"
この例では、リゾルバ仕様定義に
HR
スキーマ、OTHER
スキーマおよびPUBLIC
が指定されています。
-resolver
オプションを使用して、定義されたスキーマ内で検索するオブジェクトを指定します。前述の例では、HR
、OTHER
およびPUBLIC
で、すべてのクラス・スキーマ・オブジェクトが検索されます。スキーマで特定のクラスまたはクラス・グループのみを検索する場合は、検索範囲を絞り込むことができます。たとえば、OTHER
スキーマのmy/gui/*
クラスのみを検索するには、次のようにリゾルバ仕様を定義します。
loadjava -resolve -resolver '((* HR) ("my/gui/*" OTHER) (* PUBLIC))'
リゾルバ仕様の最初のパラメータには、クラス・スキーマ・オブジェクトを指定し、2番目のパラメータにはこれらのクラス・スキーマ・オブジェクトを検索するスキーマを定義します。
2.5.2.1 存在しないクラスへの参照の許可
リゾルバ仕様には、存在しないクラスへの未解決の参照を可能にする特別なオプションを指定できます。製品では内部クラスがまったく使用されないこともあります。標準のJava環境では、JVMはメソッドがコールされないかぎりメソッドを無視するため、問題は起こりません。ただし、クラスを解決するとき、Oracle JVMは使用できない名前も含め、そのクラスが参照しているすべての名前を解決しようとします。そのクラスが参照しているそれぞれの名前に対して一致するクラスをOracle JVMが見つけることができない場合、解決中のクラスは無効とマークされ、実行できません。
参照を無視するには、リゾルバ仕様でワイルドカードのマイナス記号(-
)を指定します。次の例は、参照先のクラスがリゾルバ仕様のスキーマ・リストに存在しない場合にも、my/gui
内のクラスへのすべての参照を許可するように指定しています。
loadjava -resolve -resolver '((* HR) (* PUBLIC) ("my/gui/*" -))'
ワイルドカードを指定しないと、あるスキーマで依存クラスが見つからないと、そのクラスは無効としてリストされ、実行できなくなります。
また、検索できなかったクラスをすべて無視するように定義することもできます。ただし、依存クラスが見つからなかった場合にも、その依存クラスを必要としているクラスが有効としてマークされる可能性があるため、この方法は危険です。ただし、依存クラスを必要としているクラスは、依存クラスなしでは実行できません。この場合は、実行時に例外となります。
HR
またはPUBLIC
に存在しないクラスをすべて無視するには、次のリゾルバ仕様を指定します。
loadjava -resolve -resolver "((* HR) (* PUBLIC) (* -))"
後でロードするクラスがマイナス記号(-)ワイルドカードを含むリゾルバを必要とするような場合は、最初からそのようなリゾルバを使用しないでください。かわりに、参照先クラスをすべてスキーマに取り込んでから、解決してください。
マイナス記号(-)ワイルドカードを使用する場合でも、クラスのスーパー・クラスは存在する可能性ガあります。スーパー・クラスが見つからない場合、リゾルバでマイナス記号(-)ワイルドカードを使用しているかどうかに関係なく、そのクラスは無効になります。
ノート:
存在しないクラスを処理する代替のメカニズムには、loadjava
ツールの-gemissing
オプションを使用します。このオプションを使用すると、loadjava
ツールによって、参照される未定義のクラス定義が作成され、ロードされます。
2.5.2.2 バイトコード検証機能
JVMの仕様では、定義したクラスをJVMで使用するには、その前に.class
ファイルを検証する必要があります。Oracle JVMでは、クラスの解決時に検証が実行されます。
次の表に、リゾルバで検出される問題と、発行される該当のOracleエラー・コードを示します。
表2-4 ORAエラー
エラー・コード | 説明 |
---|---|
|
リゾルバでクラスの形式が不正と判断されると、そのクラスは有効とマークされません。リゾルバでクラスが拒否されると、 マイナス記号(-)ワイルドカード式をリゾルバで使用し、一部のクラスの有効性を検証していない場合も、 |
|
状況によっては実行時に例外をスローできるように、リゾルバでは、有効とマークしたクラスのバイトコードが変更されることがあります。このような場合、リゾルバは |
マイナス記号(-
)ワイルドカードが指定されているリゾルバは、参照先クラスの有無に関係なく、クラスを有効とマークします。継承とインタフェースのために、あるクラスのインスタンスをスーパークラスまたは特定のインタフェースのインスタンスであるかのように使用する有効なJavaメソッドの作成が必要になる場合があります。検証対象のメソッドがクラスA
への参照をクラスB
への参照であるかのように使用している場合、リゾルバはA
がB
を拡張または実装しているかどうかを確認する必要があります。たとえば、次のメソッドについて考えてみます。シグネチャでは暗黙的にB
のインスタンスを戻すことになっていますが、そのボディはA
のインスタンスを戻します。
B myMethod(A a) { return a; }
このメソッドは、A
がクラスB
を拡張する場合、またはA
がインタフェースB
を実装している場合のみ有効です。A
またはB
の解決にマイナス記号(-)ワイルドカードが使用された場合、リゾルバはこのメソッドの安全を判断できません。この場合、myMethod
がコールされると、myMethod
のバイトコードは例外をスローするバイトコードに置換されます。
A
とB
のクラス定義が明確に識別されるスキーマにこれらがある場合、マイナス記号(-
)ワイルドカードがないリゾルバは、そのクラス定義を検索して適切に解決します。代替リゾルバの使用は、JARファイルにない他の非システム・クラスを参照する既存のJARファイルのロードが必要な場合にのみ検討します。
2.5.3 Oracle JVMでのロギング
Oracle JVMは、ロギング・プロパティ参照の領域におけるJDK JavaロギングAPIを拡張することで、ロギング構成管理のセキュリティを強化し、ユーザー・ベースのロギング構成をサポートしています。
セッション内でLogManager
をアクティブ化して、Oracle JVMのロギング・プロパティを初期化する必要があります。ロギング・プロパティは、データベース常駐リソース参照で拡張されたLogManager
APIを使用して、各セッションで1回初期化されます。
Oracle JVMでは、次のステップを実行してロギング・オプションを構成します。
javavm/lib/logging.properties
ファイル内のデフォルト設定を変更する必要がある場合は、別のプロパティ・セットを準備し、loadjava
コマンドを使用してそれらをスキーマにロードします。たとえば、スキーマがHR
であり、現行ファイル・ディレクトリがmydir
の場合、mydir
の下にディレクトリjavavm/lib/
を作成し、mydir/javavm/lib/
ディレクトリの下のlogging.properties
ファイル内に必要なプロパティを指定します。続いて、次のようにしてmydir
からloadjava
コマンドを起動します。
mydir% loadjava -u HR -v -r javavm/lib/logging.properties
password:<password>
loadjava
コマンドを起動した後は、mydir/javavm/lib/logging.properties
ファイルを削除できます。HR
として実行され、LogManager
のアクティブ化を実行しているセッションには、HR
に専用のこのデータベース常駐リソースからのプロパティでLogManager
が構成されます。
ノート:
Oracle JVMは常に、セキュリティ・マネージャを使用して実行されます。したがって、使用されているロギング構成方法に関係なく、HR
にロギング許可を付与する必要があります。ほとんどの場合、権限のあるユーザーが次のコールを発行すれば、これらの許可を付与できます。
call dbms_java.grant_permission( 'HR', 'SYS:java.util.logging.LoggingPermission', 'control', '' );
2.5.4 loadjavaツールを使用したクラスのロードの概要
loadjava
ツールを使用すると、ファイルからスキーマ・オブジェクトを生成して別のスキーマにロードできます。次に例を示します。
loadjava -u HR -schema TEST MyClass.java
Password: password
ノート:
コマンドライン・インタフェースを使用する場合、クラスをスキーマ・オブジェクトとしてデータベースにロードする必要はありません。次に例を示します。
C:\oraclehome\bin>loadjava -u HR MyClass.java
Password: password
loadjava
ツールは、SQLコマンド内から実行することもできます。ファイルからコンパイルおよびロードする従来のJVMとは異なり、Oracle JVMはデータベース・スキーマ・オブジェクトからコンパイルおよびロードします。
次の表に、従来のJVMで使用されるファイルに対応するデータベース・スキーマ・オブジェクトを示します。
表2-5 Javaファイルの説明
Javaファイルの種類 | 説明 |
---|---|
|
すべてのクラスやリソースは、データベースにロードして、そのデータベース内の他のクラスで使用できるようにする必要があります。さらに、ロード時にはデータベース内のクラスを実行できるユーザーを定義します。
次の表に、loadjava
ツールが各タイプのファイルに対して実行するアクティビティを示します。
表2-6 スキーマ・オブジェクトに対するloadjavaの操作
スキーマ・オブジェクト | オブジェクトに対するloadjavaの操作 |
---|---|
|
|
|
|
|
ノート:
dropjava
ツールは、loadjava
ツールとは逆の動作を実行します。Javaファイルに対応するスキーマ・オブジェクトを削除します。loadjava
ツールで作成したJavaスキーマ・オブジェクトは、必ずdropjava
ツールを使用して削除します。次に例を示します。
dropjava -u HR -schema TEST MyClass.java
Password: password
SQLのデータ定義言語(DDL)コマンドで削除した場合、loadjava
ツールおよびdropjava
ツールで保持している補助データは更新されません。dropjava
ツールは、SQLコマンド内から実行することもできます。
クラスとリソースをロードした後は、データベース・スキーマのUSER_OBJECTS
ビューにアクセスして、クラスとリソースが正しくロードされたことを確認できます。
2.5.4.1 ユーザー・クラスロード・クラスのメタデータの共有について
データベース常駐クラスをロードするための組込みメカニズムによってロードされたクラスはシステム・クラスロードと呼ばれ、その他の方法によってロードされたクラスはユーザー・クラスロードと呼ばれます。データベースにクラスをロードする場合、クラスの表現はメモリーで作成され、その一部はクラス・メタデータと呼ばれます。クラス・メタデータはクラスを使用するセッションと同じであり、場合によっては共有できます。以前は、システム・クラスロード・クラスの場合のみ共有できていました。Oracle Database 11gからは、システム管理者の判断により、ユーザー・クラスロード・クラスのクラス・メタデータも共有できます。
2.5.4.2 同じクラスの二重定義
同じスキーマに同じ名前の2つのクラス・オブジェクトは指定できません。この規則によって、次の2つの制限を受けることになります。
ノート:
例外は、データベース常駐JARの-prependjarnames
オプションを使用する場合です。このオプションを使用する場合、同じスキーマに同じ名前の2つのクラスを指定できます。
-
特定のJavaの
.class
ファイル、またはその.java
ファイルのいずれかはロードできますが、両方はロードできません。Oracle Databaseは、クラス・ファイルまたはソース・ファイルのどちらがロードされたかを追跡します。クラスを更新する場合は、当初ロードしたファイルと同じ種類のファイルをロードする必要があります。他の種類を更新する場合は、最初にロードしたファイルを削除してから次の種類のファイルをロードする必要があります。たとえば、クラス
y
のソースとしてx.java
をロードした場合、x.class
をロードするには、その前にx.java
を削除する必要があります。 -
同じスキーマの2つの異なるスキーマ・オブジェクトには、同じクラスを定義できません。たとえば、
x.java
でクラスy
を定義し、y
の定義をz.java
に移動するとします。x.java
がすでにロードされている場合、loadjava
ツールは、y
が定義されているz.java
のロードを拒否します。かわりに、次のいずれかの方法を実行する必要があります。-
x.java
を削除し、y
が定義されているz.java
をロードします。次にy
が定義されていない新しいx.java
をロードします。 -
y
が定義されていない新しいx.java
をロードし、次にy
が定義されているz.java
をロードします。
-
関連トピック
2.5.4.3 データベース権限とJVMパーミッションの指定について
クラスをロードするには、次のSQLデータベース権限が必要です。
-
スキーマにロードする場合は
CREATE PROCEDURE
およびCREATE TABLE
権限。 -
別のスキーマにロードする場合は
CREATE ANY PROCEDURE
およびCREATE ANY TABLE
権限。 -
oracle.aurora.security.JServerPermission.loadLibraryInClass.
classname
.
関連トピック
2.5.4.4 JARファイルまたはZIPファイルのロードについて
loadjava
ツールでは、.class
、.java
、.properties
、.sqlj
、.ser
、.jar
または.zip
ファイルを使用できます。JARファイルまたはZIPファイルには、ソース・ファイル、クラス・ファイルおよびデータファイルを挿入できます。loadjava
ツールにJARファイルまたはZIPファイルを渡すと、それはアーカイブをオープンし、そのメンバーを個別にロードします。JARまたはZIPのスキーマ・オブジェクトはありません。JARまたはZIPの内容が前回のロード時から変更されていない場合は、再ロードされません。したがって、JARファイルまたはZIPファイルのロードによるパフォーマンス低下は、ほとんどありません。実際には、JARファイルまたはZIPファイルのロードが、loadjava
ツールを使用する最も簡単な方法です。
2.5.4.5 データベース常駐JAR
11gリリース1(11.1)以降では、データベースにJARの内容をロードする場合、JAR自体を表すデータベース・オブジェクトを作成するオプションが用意されています。この方法で、JARオブジェクトと、JARからロードされたクラス、リソースおよびソース・オブジェクトとの関連付けを保持できます。その結果、次のことが可能です。
-
標準的なJVMと同じ方法で、符号付きJARとJARネームスペースの分離を使用します。
-
JARから導出したクラスを管理する一方で、それを1つの単位としてデータベースにロードします。これは、JARからロードされたクラスを個別に再定義しない場合に便利です。また、外部ファイル・システム上のJARの内容や存続に関係なく、クラスの削除時にJARからロードされたクラス・セット全体を削除できます。
JARをデータベースにロードするには、loadjava
ツールの次のオプションを使用します。
-
-jarsasdbobjects
-
-prependjarnames
関連トピック
2.5.5 実行権限の付与の概要
すべてのクラスを自分のスキーマにロードし、自分のスキーマの外部のクラスを参照しない場合は、クラスを実行する権限がすでにあります。自分のオブジェクトが同じスキーマにロードされた他のオブジェクトをコールするために必要な権限を持っています。つまり、クラスA
がクラスB
を起動する能力です。クラスA
にはクラスB
をコールする権限が付与されている必要があります。
Javaアプリケーションを定義するクラスは、その所有者のSQLスキーマの下にある、Oracle Database内に格納されます。デフォルトでは、特定のユーザーのスキーマに常駐するクラスは、セキュリティ保護のために他のユーザーからは実行できません。次の方法で、自分のクラスの実行権限を他のユーザーに付与できます。
-
loadjava -grant
オプションを使用します。 -
次のコマンドを使用します。
SQL> grant execute on myclass to HR;
myclass
は、基礎となるJavaクラスの名前です。
ノート:
Oracle Database 11gリリース1 (11.1)以前では、ストアド・プロシージャの実行権限を付与する場合、ストアド・プロシージャと、そのストアド・プロシージャによって参照されるJavaクラスの両方の実行権限が付与されます。Oracle Database 11gリリース以降では、基礎となるJavaクラスの実行権限も付与する場合、そのクラスに対する実行権限を明示的に付与する必要があります。これは、セキュリティの向上を目的として実装されています。
次の図は、クラスを実行するために必要な権限を示しています。
2.5.6 現行ユーザーの制御の概要
PL/SQLコードの実行中は、常に現行ユーザーが存在します。Javaコードの実行にも同じ概念が使用されます。まず、現行ユーザーは、Javaコードを起動するセッションを作成するユーザーです。Javaメソッドは、対応するラッパーによってSQLまたはPL/SQLからコールされます。Javaラッパーは、JavaメソッドをPL/SQLストアド・プロシージャまたはファンクションとしてSQLおよびPL/SQLに公開する特殊なPL/SQLエンティティです。このようなラッパーは、有効な現行ユーザーを変更できます。有効な現行ユーザーをラッパーの所有者に変更するラッパーは、定義者権限ラッパーと呼ばれます。ラッパーが有効な現行ユーザーを変更しない場合、有効なユーザーはそのまま変わりません。
Javaラッパーは、デフォルトで定義者権限ラッパーです。これをオーバーライドするには、AUTHID CURRENT_USER
オプションを使用してラッパーを作成します。
Javaコードの実行中は常に、Javaコール・スタックが保持されます。スタックには、現在実行中のメソッドに対応する最も内側のフレームを含め、入力したJavaメソッドに対応するフレームがあります。デフォルトでは、Javaメソッドは、スタックで、現行ユーザーを変更せずに、つまり定義者権限ではなく現在の有効な実行者権限で、実行されます。
Javaクラスは、loadjava -definer
オプションを使用してデータベースにロードできます。定義者属性がマークされているクラスのメソッドは、定義者権限メソッドになります。このようなメソッドが入力されると、定義者フレームと呼ばれる特殊なフレームがJavaスタックに作成されます。このフレームは、有効な現行ユーザーをこのようなクラスの所有者(定義者)に切り替えます。新しいユーザーIDは、定義者フレームがスタックからなくなるまで、あるいはネストされた定義者フレームが入力されるまで、すべての内部フレームに対して有効です。
したがって、SQLまたはPL/SQLからそのラッパーによってコールされたJavaメソッドの実行中は常に、有効なユーザーは次のいずれかになります。
-
Javaスタックの最内部の定義者フレーム
-
最上部JavaメソッドのPL/SQLラッパーの所有者(定義者権限の場合)またはラッパーをコールしたユーザー。
販売分析に定義者権限プロシージャを使用する企業を考えてみます。地区ごとの販売統計を提供するには、analyze
プロシージャによって各地区のsales
表にアクセスする必要があります。そのためには、各地区サイトにプロシージャが存在している必要があります。これによりメンテナンス上の問題が発生します。問題を解決するために、この企業ではanalyze
プロシージャの実行者権限バージョンを本社にインストールしました。
次の図に示すように、すべての地区サイトで同じプロシージャを使用して、各地区のsales
表を問合せできます。
実行者権限のデフォルト動作のオーバーライドが必要になる場合もあります。本社がanalyze
プロシージャを使用して販売手数料を算出し、中央のpayroll
表を更新する場合を考えます。analyze
の実行者が従業員の給料や他の機密性の高いデータが格納されているpayroll
表に直接アクセスすることは問題です。
次の図に示すように、analyze
プロシージャから定義者権限プロシージャcalcComm
をコールし、このプロシージャでpayroll
表を更新することで解決します。
関連トピック
2.5.7 Javaアップロードのチェックの概要
USER_OBJECTS
データベース・ビューを問い合せることで、Javaソース、クラスおよびリソースを含め、独自に所有しているスキーマ・オブジェクトに関する情報を取得できます。たとえば、ロードしたソース、クラスまたはリソースがスキーマ・オブジェクトに正しく格納されているかどうかを確認できます。
次の表に、USER_OBJECTS
の主な列とその説明を示します。
表2-7 主なUSER_OBJECT列
名前 | 説明 |
---|---|
|
オブジェクト名 |
|
|
|
オブジェクトのステータス。値は、 |
オブジェクト名とオブジェクト・タイプ
USER_OBJECTS
のOBJECT_NAME
は別名です。30文字を超える完全修飾名は別名で格納されます。
サーバーでスキーマ・オブジェクトの別名を使用する場合は、別名や変換規則が不明であっても、DBMS_JAVA
パッケージのLONGNAME()
ファンクションを使用することで、完全修飾名による問合せから別名を取得できます。
SQL> SELECT dbms_java.longname(object_name) FROM user_objects WHERE object_type='JAVA SOURCE';
この文を実行すると、Javaソース・スキーマ・オブジェクトの完全修飾名が表示されます。別名が使用されていない場合、変換は実行されません。
ノート:
SQLおよびPL/SQLでは、大/小文字は区別されません。
データベースで別名に変換されたかどうかが不明であっても、DBMS_JAVA
パッケージのSHORTNAME()
ファンクションを使用することで、問合せ基準として完全修飾名を使用できます。
SQL*Plus> SELECT object_type FROM user_objects WHERE object_name=dbms_java.shortname('known_fullname');
この文を実行すると、指定された完全修飾名のスキーマ・オブジェクトのOBJECT_TYPE
が表示されます。ただし、完全修飾名をデータベース文字セットで表現できることが前提となります。
SQL> select * from javasnm; SHORT LONGNAME ---------------------------------------------------------------------- /78e6d350_BinaryExceptionHandl sun/tools/java/BinaryExceptionHandler /b6c774bb_ClassDeclaration sun/tools/java/ClassDeclaration /af5a8ef3_JarVerifierStream1 sun/tools/jar/JarVerifierStream$1
この文を実行すると、javasnm
ビューに保存されたすべてのデータが表示されます。
Status (状態)
STATUS
は、Javaスキーマ・オブジェクトの妥当性を示す文字列です。Javaソース・スキーマ・オブジェクトは、正常にコンパイルされるとVALID
と表示され、Javaクラス・スキーマ・オブジェクトは、正しく解決されるとVALID
と表示されます。リソースは解決されないため、Javaリソース・スキーマ・オブジェクトは常にVALID
です。
例: USER_OBJECTSへのアクセス
次のSQL*Plusスクリプトは、USER_OBJECTS
ビューにアクセスして、アップロードされたJavaソース、クラスおよびリソースの情報を表示します。
COL object_name format a30 COL object_type format a15 SELECT object_name, object_type, status FROM user_objects WHERE object_type IN ('JAVA SOURCE', 'JAVA CLASS', 'JAVA RESOURCE') ORDER BY object_type, object_name;
次の例のように、必要な場合はUSER_OBJECTS
の問合せにワイルドカードを使用できます。
SELECT object_name, object_type, status FROM user_objects WHERE object_name LIKE '%Alerter';
この文は、Alerter
の文字で終わるOBJECT_NAME
エントリを検索します。
関連トピック
2.5.8 データベースにロードされたJavaメソッドの公開について
Oracle Databaseでは、データベースにロードされたJavaメソッドは、公開されるとクライアントおよびSQLからコールできるようになります。オブジェクト自体、または個々のメソッドを公開できます。SQLのデータ操作言語(DML)文またはPL/SQLで、直接あるいは間接的にトリガーでコールするJavaストアド・プロシージャを作成する場合は、クラスの個々のメソッドを公開する必要があります。コール仕様を使用してメソッドへのアクセス方法を指定します。Javaプログラムは多数のクラスの様々なメソッドで構成されます。ただし、コール仕様で通常公開されるstatic
メソッドは少数です。
関連トピック
2.5.9 データベースにロードされたJavaクラスの監査の概要
Oracle Database 10gリリース2(10.2)より前のリリースでは、データベース内のJavaクラスは直接監査できません。ただし、PL/SQLラッパーは監査できます。通常、Javaストアド・プロシージャはすべて同じラッパーから起動されます。したがって、Javaストアド・プロシージャはすべて、直接ではありませんが監査可能です。
他のDDL文と同様に、Oracle Database 10gリリース2(10.2)以降では、ソース、クラスおよびリソースのJavaスキーマ・オブジェクトを作成、変更または削除するDDL文を監査できます。Oracle Databaseには、Javaアクティビティを簡単かつ直接的に監査するための監査オプションが用意されています。また、Javaソース、クラスおよびリソースの変更も監査できます。
Javaスキーマ・オブジェクトに関連するデータベース・アクティビティを、文レベルおよびオブジェクト・レベルの2種類のレベルで監査できます。文レベルでは、特定パターンの文に関連したすべてのアクティビティを監査できます。
表2-8に、Javaスキーマ・オブジェクトに関連する文監査オプションと対応するSQL文を示します。
表2-8 Javaスキーマ・オブジェクトに関連する文監査オプション
文のオプション | SQL文 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
たとえば、ALTER JAVA SOURCE
のDDL文を監査する場合は、SQLプロンプトに次の文を入力します。
AUDIT ALTER JAVA SOURCE
オブジェクト・レベルの監査では、より詳細な監査が可能です。これは、特定のオブジェクトをクローズアップすることで、特定の問題を識別できます。
表2-9に、各Javaスキーマ・オブジェクトごとのオブジェクト監査オプションを示しています。セル内のエントリXは、そのJavaスキーマ・オブジェクトについて、対応するSQLコマンドを監査できることを示します。エントリNAは、そのJavaスキーマ・オブジェクトについて対応するSQLコマンドが適用不可であることを示します。
表2-9 Javaスキーマ・オプションに関連するオブジェクト監査オプション
オブジェクト・オプション | Javaソース | Javaリソース | Javaクラス |
---|---|---|---|
|
X |
NA |
X |
|
NA |
NA |
X |
|
X |
X |
X |
|
X |
X |
X |