2.5 Javaクラス・メソッドの実行準備

Javaメソッドを実行するには、次の準備が必要です。

  1. Javaソース・コードをいつコンパイルするかを決定します。
  2. データベース内のJavaクラスの位置の特定に、デフォルトのリゾルバを使用するか、別のリゾルバを使用するかを決定します。
  3. クラスをデータベースにロードします。クラスにデフォルトのリゾルバを使用しない場合は、ロード・コマンドで別のリゾルバを指定してください。
  4. クラスまたはメソッドを公開します。

2.5.1 Javaクラスのコンパイル

Javaソース・コードのコンパイルは、次のいずれかの方法で実行できます。

  • クライアント・システムでソースを明示的にコンパイルしてから、javacなどのJavaコンパイラを介してデータベースにロードできます。

  • データベースに対して、loadjavaツールで管理されるロード・プロセス中にソースをコンパイルするように指定できます。

  • 実行時に動的なコンパイルを強制できます。

注意:

loadjavaツールを使用してコンパイルを実行する場合は、コンパイラ・オプションを指定できます。

この項には次のトピックが含まれます:

2.5.1.1 javacによるソースのコンパイル

次の例に示すように、従来のJavaコンパイラを使用してJavaソース・コードをコンパイルできます。

javac <file_name>.java

コンパイルが終了した後は、ソースではなく、コンパイル済バイナリをデータベースにロードします。通常は、データベースでデバッグするよりも、各自のシステムでJavaコードをデバッグする方が簡単なため、これは便利なオプションです。

2.5.1.2 loadjavaツールを使用したソースのコンパイル

ソース・ファイルのloadjavaツールに-resolveオプションを指定すると、次の処理が実行されます。

  1. ソース・ファイルがソース・スキーマ・オブジェクトとしてロードされます。
  2. ソース・ファイルがコンパイルされます。
  3. コンパイル済の.javaファイルに定義されている各クラスに対して、クラス・スキーマ・オブジェクトが作成されます。
  4. コンパイル済のコードがクラス・スキーマ・オブジェクトに格納されます。

Oracle Databaseによって、すべてのコンパイル・エラーがloadjavaツールのログ・ファイルとUSER_ERRORSビューに書き込まれます。

2.5.1.3 実行時におけるソースのコンパイル

次のように、-resolveオプションを指定せずにデータベースにJavaソースをロードするとします。

loadjava <file_name>.java

この場合、実行時にクラスが必要になったときに、ソースが自動的にコンパイルされます。ソース・ファイルは、ソース・スキーマ・オブジェクトにロードされます。Oracle Databaseによって、すべてのコンパイル・エラーがloadjavaツールのログ・ファイルとUSER_ERRORSビューに書き込まれます。

2.5.1.4 コンパイラ・オプションの指定

コンパイラ・オプションを指定するには、次の方法があります。

  • loadjavaツールのコマンドラインにコンパイラ・オプションを指定します。loadjavaツールには、encodingオプションを指定することもできます。

  • JAVA$OPTIONS表に永続コンパイラ・オプションを指定します。JAVA$OPTIONS表はスキーマごとに存在します。コンパイルする度に、これらのオプションが使用されます。ただし、loadjavaツールにコンパイラ・オプションを指定すると、この表に定義されているオプションはオーバーライドされます。この方法でコンパイラ・オプションを指定する場合は、この表を独自に作成する必要があります。

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ソース・スキーマ・オブジェクトのコンパイルに使用するオプションがJAVA$OPTIONS表で検索された場合は、スキーマ・オブジェクトの完全修飾されたクラス名に最も近いnameの値の行が使用されます。値が空文字列のnameは、あらゆるスキーマ・オブジェクト名に一致します。

option

optionパラメータは、onlineencodingまたはdebugです。

最初、スキーマには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

online

true

  • a.b.c.d

    : パターンに完全一致しています。

  • a.b.c.d.e

    : 先頭部分がパターンに完全一致しています。完全修飾名に一致する他の規則はありません。

a.b

online

false

  • a.b

    : パターンに完全一致しています。

  • a.b.c.x

    : 先頭部分がパターンに完全一致しています。この規則以外に一致する規則はありません。

空文字列

online

true

  • a.c

    : 定義済の名前に一致するパターンはありません。デフォルトは空文字列規則です。

  • x.y

    : 定義済の名前に一致するパターンはありません。デフォルトは空文字列規則です。

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()
  }
}

システムは詳細なクラス・レベルで依存関係を追跡します。この例では、ABのインスタンスを保持し、BCのインスタンスを保持し、CAのインスタンスを保持しているため、クラスABおよびCが相互に依存しています。クラスAに新しいフィールドを追加して、このクラスの定義を変更すると、Oracle Databaseの依存関係メカニズムによって、クラスBCが無効になったことを示すフラグが設定されます。これらのクラスを次に使用する前に、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オプションを使用して、定義されたスキーマ内で検索するオブジェクトを指定します。前述の例では、HROTHERおよび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エラー

エラー・コード 説明

ORA-29545

リゾルバでクラスの形式が不正と判断されると、そのクラスは有効とマークされません。リゾルバでクラスが拒否されると、ORA-29545エラーが発行されます。このエラーはloadjavaツールによってレポートされます。たとえば、.classファイルの内容がJavaコンパイルの結果に一致しない場合、またはファイルが破損している場合は、このエラーがスローされます。

マイナス記号(-)ワイルドカード式をリゾルバで使用し、一部のクラスの有効性を検証していない場合も、ORA-29545エラーが発生することがあります。

ORA-29552

状況によっては実行時に例外をスローできるように、リゾルバでは、有効とマークしたクラスのバイトコードが変更されることがあります。このような場合、リゾルバはORA-29552警告を発行し、loadjavaツールがこのエラーをレポートします。Java言語仕様(JLS)でIncompatibleClassChangeErrorがスローされるように規定されている場合は、loadjavaツールがこの警告を発行します。Oracle JVMは、リゾルバにこのような状況を検出させることで、JLSで規定されているランタイム動作をサポートします。

マイナス記号(-)ワイルドカードが指定されているリゾルバは、参照先クラスの有無に関係なく、クラスを有効とマークします。継承とインタフェースのために、あるクラスのインスタンスをスーパークラスまたは特定のインタフェースのインスタンスであるかのように使用する有効なJavaメソッドの作成が必要になる場合があります。検証対象のメソッドがクラスAへの参照をクラスBへの参照であるかのように使用している場合、リゾルバはABを拡張または実装しているかどうかを確認する必要があります。たとえば、次のメソッドについて考えてみます。シグネチャでは暗黙的にBのインスタンスを戻すことになっていますが、そのボディはAのインスタンスを戻します。

B myMethod(A a)
{ 
  return a; 
}

このメソッドは、AがクラスBを拡張する場合、またはAがインタフェースBを実装している場合のみ有効です。AまたはBの解決にマイナス記号(-)ワイルドカードが使用された場合、リゾルバはこのメソッドの安全を判断できません。この場合、myMethodがコールされると、myMethodのバイトコードは例外をスローするバイトコードに置換されます。

ABのクラス定義が明確に識別されるスキーマにこれらがある場合、マイナス記号(-)ワイルドカードがないリゾルバは、そのクラス定義を検索して適切に解決します。代替リゾルバの使用は、JARファイルにない他の非システム・クラスを参照する既存のJARファイルのロードが必要な場合にのみ検討します。

2.5.3 Oracle JVMでのロギング

Oracle JVMは、ロギング・プロパティ参照の領域におけるJDK JavaロギングAPIを拡張することで、ロギング構成管理のセキュリティを強化し、ユーザー・ベースのロギング構成をサポートしています。

関連項目:

JavaロギングAPIの詳細は、次のサイトを参照してください。

http://docs.oracle.com/javase/7/docs/

セッション内でLogManagerをアクティブ化して、Oracle JVMのロギング・プロパティを初期化する必要があります。ロギング・プロパティは、データベース常駐リソース参照で拡張されたLogManager APIを使用して、各セッションで1回初期化されます。

Oracle JVMでは、次のステップを実行してロギング・オプションを構成します。

  1. java.util.logging.config.classプロパティが設定されている場合、ロギングの動作は標準JDKでの動作と同じです。
  2. java.util.logging.config.classプロパティが設定されていない場合、Oracle JVMでは現行ユーザー・スキーマのjavavm/lib/logging.propertiesリソースの可用性が検証されます。

    使用可能な場合、このリソースがLogManagerの構成設定として使用され、java.util.logging.config.fileプロパティが設定されます。

  3. 前述の条件の両方には該当しない場合、java.util.logging.config.fileプロパティが検証され、これが指定されていれば、LogManager APIで記述されているとおりに使用されます。
  4. ステップ1、2および3のいずれの条件にも該当しない場合は、SYSスキーマのjavavm/lib/logging.propertiesリソースが使用されます。このリソースは、データベースの作成時にSYSスキーマにロードされた$(java.home)/lib/logging.propertiesファイルのコピーです。つまり、デフォルトでLogManagerは、$(java.home)/javavm/lib/logging.propertiesファイルで構成されている場合と同様に動作します。ただし、このファイルを変更しても、データベースが再作成されるまで変更は有効になりません。

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ファイルの種類 説明

.javaソース・ファイルまたは.sqljソース・ファイル

Javaソース・スキーマ・オブジェクトに対応

.classコンパイル済Javaファイル

Javaクラス・スキーマ・オブジェクトに対応

.properties Javaリソース・ファイル、.ser SQLJプロファイル・ファイルまたはデータファイル

Javaリソース・スキーマ・オブジェクトに対応

すべてのクラスやリソースは、データベースにロードして、そのデータベース内の他のクラスで使用できるようにする必要があります。さらに、ロード時にはデータベース内のクラスを実行できるユーザーを定義します。

次の表に、loadjavaツールが各タイプのファイルに対して実行するアクティビティを示します。

表2-6 スキーマ・オブジェクトに対するloadjavaの操作

スキーマ・オブジェクト オブジェクトに対するloadjavaの操作

.javaソース・ファイル

  1. 別のスキーマが指定されていない場合は、定義者のスキーマにJavaソース・スキーマ・オブジェクトを作成します。

  2. スキーマ・オブジェクトにソース・ファイルの内容をロードします。

  3. ソース・ファイルに定義されているすべてのクラスに、クラス・スキーマ・オブジェクトを作成します。

  4. -resolveが指定された場合は、ソース・スキーマ・オブジェクトをコンパイルし、クラスとその依存関係を解決します。次に、コンパイル済のクラスをクラス・スキーマ・オブジェクトに格納します。

.sqljソース・ファイル

  1. 別のスキーマが指定されていない場合は、定義者のスキーマにソース・スキーマ・オブジェクトを作成します。

  2. スキーマ・オブジェクトにソース・ファイルの内容をロードします。

  3. ソース・ファイルに定義されているすべてのクラスとリソースに、クラス・スキーマ・オブジェクトを作成します。

  4. -resolveが指定された場合は、ソース・スキーマ・オブジェクトを変換およびコンパイルし、コンパイル済のクラスをクラス・スキーマ・オブジェクトに格納します。次に、プロファイルを.serリソース・スキーマ・オブジェクトに格納し、それをカスタマイズします。

.classコンパイル済Javaファイル

  1. 別のスキーマが指定されていない場合は、定義者のスキーマにクラス・スキーマ・オブジェクトを作成します。

  2. クラス・ファイルをスキーマ・オブジェクトにロードします。

  3. -resolveが指定された場合は、クラスおよびその依存関係を解決して検証します。

.properties Javaリソース・ファイル

  1. 別のスキーマが指定されていない場合は、定義者のスキーマにリソース・スキーマ・オブジェクトを作成します。

  2. リソース・ファイルをスキーマ・オブジェクトにロードします。

.ser SQLJプロファイル

  1. 別のスキーマが指定されていない場合は、定義者のスキーマにリソース・スキーマ・オブジェクトを作成します。

  2. .serリソース・ファイルをスキーマ・オブジェクトにロードし、ファイルをカスタマイズします。

注意:

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ツールを使用する最も簡単な方法です。

注意:

前回のロード時から変更がない場合、Oracle Databaseはクラスを再ロードしません。ただし、-forceオプションを使用することで、強制的にクラスを再ロードできます。

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-3 クラスの実行権限

図2-3の説明が続きます
「図2-3 クラスの実行権限」の説明

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表を問合せできます。

図2-4 実行者権限のソリューション

図2-4の説明が続きます
「図2-4 実行者権限のソリューション」の説明

実行者権限のデフォルト動作のオーバーライドが必要になる場合もあります。本社がanalyzeプロシージャを使用して販売手数料を算出し、中央のpayroll表を更新する場合を考えます。analyzeの実行者が従業員の給料や他の機密性の高いデータが格納されているpayroll表に直接アクセスすることは問題です。

次の図に示すように、analyzeプロシージャから定義者権限プロシージャcalcCommをコールし、このプロシージャでpayroll表を更新することで解決します。

図2-5 間接的なアクセス

図2-5の説明が続きます
「図2-5 間接的なアクセス」の説明

2.5.7 Javaアップロードのチェックの概要

USER_OBJECTSデータベース・ビューを問い合せることで、Javaソース、クラスおよびリソースを含め、独自に所有しているスキーマ・オブジェクトに関する情報を取得できます。たとえば、ロードしたソース、クラスまたはリソースがスキーマ・オブジェクトに正しく格納されているかどうかを確認できます。

次の表に、USER_OBJECTSの主な列とその説明を示します。

表2-7 主なUSER_OBJECT列

名前 説明

OBJECT_NAME

オブジェクト名

OBJECT_TYPE

JAVA SOURCEJAVA CLASSJAVA RESOURCEなど、オブジェクトのタイプ。

STATUS

オブジェクトのステータス。値は、VALIDまたはINVALIDのいずれかです。JAVA RESOURCEに対しては常にVALIDとなります。

オブジェクト名とオブジェクト・タイプ

USER_OBJECTSOBJECT_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文

CREATE JAVA SOURCE

CREATE JAVA SOURCE

CREATE OR REPLACE JAVA SOURCE

ALTER JAVA SOURCE

ALTER JAVA SOURCE

DROP JAVA SOURCE

DROP JAVA SOURCE

CREATE JAVA CLASS

CREATE JAVA CLASS

CREATE OR REPLACE JAVA CLASS

ALTER JAVA CLASS

ALTER JAVA CLASS

DROP JAVA CLASS

DROP JAVA CLASS

CREATE JAVA RESOURCE

CREATE JAVA RESOURCE

CREATE OR REPLACE JAVA RESOURCE

ALTER JAVA RESOURCE

ALTER JAVA RESOURCE

DROP JAVA RESOURCE

DROP JAVA RESOURCE

たとえば、ALTER JAVA SOURCEのDDL文を監査する場合は、SQLプロンプトに次の文を入力します。

AUDIT ALTER JAVA SOURCE

オブジェクト・レベルの監査では、より詳細な監査が可能です。これは、特定のオブジェクトをクローズアップすることで、特定の問題を識別できます。

表2-9に、各Javaスキーマ・オブジェクトごとのオブジェクト監査オプションを示しています。セル内のエントリXは、そのJavaスキーマ・オブジェクトについて、対応するSQLコマンドを監査できることを示します。エントリNAは、そのJavaスキーマ・オブジェクトについて対応するSQLコマンドが適用不可であることを示します。

表2-9 Javaスキーマ・オプションに関連するオブジェクト監査オプション

オブジェクト・オプション Javaソース Javaリソース Javaクラス

ALTER

X

NA

X

EXECUTE

NA

NA

X

AUDIT

X

X

X

GRANT

X

X

X