Oracle® Database

Java開発者ガイド

12cリリース1 (12.1)

B72466-05(原本部品番号:E50793-03)

2014年6月

このマニュアルでは、Oracle DatabaseでJavaアプリケーションを開発、ロードおよび実行する方法について説明します。

Oracle Database Java開発者ガイド 12cリリース1 (12.1)

B72466-05

Copyright © 1999, 2014, Oracle and/or its affiliates.All rights reserved.

原本著者:  Tulika Das、Sheryl Maring、Rick Sapir、Michael Wiesenberg

原本協力者:  Tanmay Choudhury、Venkatasubramaniam Iyer、Brian Wright、Timothy Smith

原本協力者:  Oracle Database 12cのドキュメントを、本リリースに携わった全員にとって創造の源となったMark Townsendに捧げます。

原本協力者: Kuassi Mensah、Mark Jungerman、Suresh Srinivasan、Ernest Tucker、Robert H Lee、Dmitry Nizhegorodov、Nataraju Neeluru、David Unietis、Paul Lo、Malik Kalfane、Steve Harris、Ellen Barnes、Peter Benson、Greg Colvin、Bill Courington、Matthieu Devin、Jim Haungs、Hal Hildebrand、Susan Kraft、Thomas Kurian、Scott Meyer、Tom Portfolio、Dave Rosenberg、Jerry Schwarz、Harlan Sexton、Xuhua Li

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントが、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供される場合は、次のNoticeが適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

目次

例一覧

図一覧

表一覧

タイトルおよび著作権情報

はじめに

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

『Oracle Database Java開発者ガイド』のこのリリースでの変更点

- Oracle Database 12c リリース1 (12.1)の変更点

1 Oracle DatabaseにおけるJavaの概要

- Javaの概要

- Javaおよびオブジェクト指向プログラミングの用語

- クラス

- オブジェクト

- 継承

- インタフェース

- カプセル化

- ポリモフィズム

- Java言語の主な機能

- Java仮想マシン

- Javaクラス階層

- Oracle DatabaseにおけるJavaの使用

- JavaとRDBMS: 堅牢な組合せ

- マルチスレッド

- メモリー領域管理

- フットプリント

- Oracle JVMのパフォーマンス

- 動的クラス・ロード

- Oracle JVMの概要

- プロセス領域

- Javaセッションの初期化、期間およびエントリ・ポイント

- GUI

- IDE

- Oracle JVMの機能リスト

- Oracle JVMの主要コンポーネント

- ライブラリ・マネージャ

- コンパイラ

- インタプリタ

- クラス・ローダー

- 検証機能

- サーバー側JDBC内部ドライバ

- サーバー側SQLJトランスレータ

- システム・クラス

- OracleのJavaアプリケーション方針

- データベース・アプリケーション開発におけるJava

- Javaプログラミング環境

- Javaストアド・プロシージャ

- PL/SQLの統合とOracle RDBMSの機能

- JDBCドライバ

- SQLJ

- JPublisher

- 開発ツール

- Internet Protocol Version 6のサポート

- 複数のJDKのサポート

- 既存のデータベースを使用しない

- 既存のデータベースを使用する

- 専用モード・セッションのメモリー・モデル

2 Oracle DatabaseでのJavaアプリケーション

- Javaアプリケーションにインポーズされるデータベース・セッション

- Javaアプリケーションの実行制御

- Javaのコード、バイナリおよびリソースの格納

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

- Javaクラスのコンパイル

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

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

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

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

- 自動再コンパイル

- クラス依存関係の解決

- Oracle JVMでのロギング

- クラスのロード

- 実行権限の付与

- 現行ユーザーの制御

- Javaアップロードのチェック

- 公開

- 監査

- サーバー上のユーザー・インタフェース

- クラスの短縮名

- Oracle DatabaseのClass.forName()

- Class.forName()へのClassLoaderの指定

- classForNameAndSchema()へのクラス名とスキーマ名の指定

- lookupClass()へのクラス名とスキーマ名の指定

- シリアライズでのクラス名とスキーマ名の指定

- Class.forNameの例

- オペレーティング・システム・リソースの管理

- オペレーティング・システム・リソースの概要

- ガベージ・コレクションとオペレーティング・システム・リソース

- Oracle DatabaseでのRuntime.exec機能の使用

- JMXを使用したアプリケーションの管理

- JMXの概要

- セッションでのJMXの有効化と起動

- Oracle JVM JMXのデフォルト設定と構成可能性

- dbms_java.start_jmx_agentへのSQLコールの例

- JConsoleを使用したOracle JVMの監視および制御

- jconsoleコマンド

- JConsoleインタフェース

- OracleRuntime MBean

- メモリーのしきい値

- セキュリティに関する重要な注意点

- JMXの共有サーバーの制限事項

- Oracle Databaseのスレッド

- 共有サーバーに関する考慮事項

- コール終了時の移行

- コール終了時の最適化に対するOracle固有のサポート

- EndOfCallRegistry.registerCallback()メソッド

- EndOfCallRegistry.runCallbacks()メソッド

- Callbackインタフェース

- Callback.act()メソッド

- 複数のコールに影響を与えるオペレーティング・システム・リソース

3 Oracle DatabaseでのJavaメソッドのコール

- Javaメソッドの起動

- PL/SQLラッパーの使用

- JNIサポート

- データベースでのSQLJおよびJDBCとJavaの併用

- JDBC

- SQLJ

- JDBCとSQLJの比較例

- 完全なSQLJの例

- SQLJの強い型指定

- SQLJプログラムの変換

- サーバー上でのSQLJプログラムの実行

- サーバー上で実行するためのクライアント・アプリケーションの変換

- PL/SQLとの対話

- コマンドライン・インタフェースの使用

- クライアント側スタブの使用

- サーバー上での実行を識別する方法

- サーバー上の出力のリダイレクト

- データベースでのJavaの直接コール

4 Javaのインストールと構成

- Java対応のデータベースの初期化

- Oracle Databaseのテンプレートを使用した構成

- Oracle JVMを組み込むための既存のOracle Databaseの変更

- Oracle JVMの構成

- DBMS_JAVAパッケージの使用方法

- Javaクライアントを使用可能にする方法

- クライアントへのJava SEのインストール

- 環境変数の設定

- サンプルを使用したインストールのテスト

- Javaセッションの状態に使用する2層の期間

- システム・プロパティの設定

5 Javaストアド・プロシージャの開発

- ストアド・プロシージャとランタイム・コンテキスト

- ファンクションおよびプロシージャ

- データベース・トリガー

- オブジェクト・リレーショナル・メソッド

- ストアド・プロシージャの利点

- パフォーマンス

- 生産性と使いやすさ

- スケーラビリティ

- メンテナンス性

- 相互運用性

- レプリケーション

- セキュリティ

- Javaストアド・プロシージャの手順

- 手順1: Javaクラスの作成または再利用

- 手順2: Javaクラスのロードおよび解決

- 手順3: Javaクラスの公開

- 手順4: ストアド・プロシージャのコール

- Javaストアド・プロシージャのデバッグ

- Javaストアド・プロシージャのデバッグの前提条件

- jdbデバッガを使用したJavaストアド・プロシージャのデバッグ

- JDeveloperを使用したJavaストアド・プロシージャのデバッグ

6 コール仕様を使用したJavaクラスの公開

- コール仕様の概要

- コール仕様の定義

- パラメータ・モードの設定

- データ型のマッピング

- サーバー側JDBC内部ドライバの使用

- トップレベルのコール仕様の作成

- パッケージのコール仕様の記述

- オブジェクト型コール仕様の記述

- 属性の宣言

- メソッドの宣言

- マップ・メソッドとオーダー・メソッド

- コンストラクタ・メソッド

- 例

7 ストアド・プロシージャのコール

- トップレベルからのJavaのコール

- 出力のリダイレクト

- トップレベルからのJavaストアド・プロシージャのコールの例

- データベース・トリガーからのJavaのコール

- SQL DMLからのJavaのコール

- PL/SQLからのJavaのコール

- JavaからのPL/SQLのコール

- Oracle JVMによる例外の処理方法

8 Javaストアド・プロシージャのアプリケーションの例

- データベース・スキーマの計画

- データベース表の作成

- Javaクラスの作成

- Javaクラスのロード

- Javaクラスの公開

- Javaストアド・プロシージャのコール

9 Oracle Database Javaアプリケーションのパフォーマンス

- Oracle JVMのJust-In-Time(JIT)コンパイラ

- Oracle JVMのJITの概要

- JITコンパイルの利点

- Oracle Database 11gで導入されたメソッド

- Javaのメモリー使用量

- メモリー初期化パラメータの構成

- データベース・テンプレート内のプール・サイズの初期化

- Javaプール・メモリー

- Javaプール・メモリー使用量の表示

- メモリー不足エラーの修正

- Javaコールおよびセッション・ヒープ統計情報の表示

10 Oracle Database Javaアプリケーションのセキュリティ

- ネットワーク接続のセキュリティ

- データベース・コンテンツとOracle JVMセキュリティ

- Java 2セキュリティ

- パーミッションの設定

- 各パーミッションのファイングレイン定義

- ロールに割り当てられる一般的なパーミッション定義

- デバッグのパーミッション

- クラスをロードするためのパーミッション

- デフォルトのjava.securityリソースのカスタマイズ

- データベース認証のメカニズム

- Oracle DatabaseでのRuntime.exec機能のセキュアな使用

11 JNDIに対するOracle JVMのネイティブ・サポート

- JNDIに対するOracle JVMのサポートの概要

- JNDIに対するOracle JVMのサポートの要件

- ネームスペース

- オブジェクト許可

- 永続記憶域表、索引および順序

- 初期のコンテキストおよび許可

- オブジェクトおよびコンテキストのデフォルト許可

- Oracle Java Directory ServiceのJNDIネームスペース・プロバイダ

- ディレクトリ・コンテキスト

- StateFactory

- ObjectFactory

- OJDS URLのサポート

- クライアント・クラスパス

- ネームスペース・ブラウザ

- OJDSのコマンドライン・ツール

- lsコマンド

- cdコマンド

- pwdコマンド

- chownコマンド

- mkdirコマンド

- rmコマンド

- lnコマンド

- mvコマンド

- chmodコマンド

- bindコマンド

- binddsコマンド

- bindurlコマンド

- OJDSのAPIおよびクラス

- oracle.aurora.jndi.ojds.OjdsClientContext

- oracle.aurora.jndi.ojds.OjdsServerContext

- oracle.aurora.jndi.ojds.OjdsInitialContextFactory

- oracle.aurora.jndi.ojds.OjdsURLContextFactory

- oracle.aurora.jndi.ojds.OjdsURLContext

12 スキーマ・オブジェクトおよびOracle JVMユーティリティ

- スキーマ・オブジェクトの概要

- ロード内容とロード時期

- スキーマ・オブジェクトの解決

- スキーマ・オブジェクトのコンパイル

- ojvmtcツール

- loadjavaツール

- 構文

- 引数の概要

- 引数の詳細

- dropjavaツール

- 構文

- 引数の概要

- 引数の詳細

- リソースの削除

- ojvmjavaツール

- 構文

- 引数の概要

- 例

- 機能

- ojvmjavaツールのコマンドライン・オプション

- シェル・コマンド

13 データベースWebサービス

- データベースWebサービスの概要

- Webサービス・プロバイダとしてのOracle Databaseの使用

- WebサービスからのコールでのJPublisherの使用方法

- Webサービス・プロバイダとしてのOracle Databaseの機能

- WebサービスからのOracle DatabaseのコールをサポートするJPublisher

- Webサービス・コンシューマとしてのOracle Databaseの使用

- WebサービスのコールでのOracle Databaseの使用方法

- Webサービスのデータソース(仮想表サポート)

- Webサービス・コンシューマとしてのOracle Databaseの機能

- JPublisherにおける生成の概要

- SQL型のマッピングの調整

A DBMS_JAVAパッケージ

- longname

- shortname

- get_compiler_option

- set_compiler_option

- reset_compiler_option

- resolver

- derivedFrom

- fixed_in_instance

- set_output

- export_source

- export_class

- export_resource

- loadjava

- dropjava

- grant_permission

- grant_permission

- restrict_permission

- restrict_permission

- grant_policy_permission

- grant_policy_permission

- revoke_permission

- disable_permission

- enable_permission

- delete_permission

- set_preference

- runjava

- runjava_in_current_session

- set_property

- get_property

- remove_property

- show_property

- set_output_to_sql

- remove_output_to_sql

- enable_output_to_sql

- disable_output_to_sql

- query_output_to_sql

- set_output_to_java

- remove_output_to_java

- enable_output_to_java

- disable_output_to_java

- query_output_to_java

- set_output_to_file

- remove_output_to_file

- enable_output_to_file

- disable_output_to_file

- query_output_to_file

- enable_output_to_trc

- disable_output_to_trc

- query_output_to_trc

- endsession

- endsession_and_related_state

- set_native_compiler_option

- unset_native_compiler_option

- compile_class

- uncompile_class

- compile_method

- uncompile_method

- start_jmx_agent

- set_runtime_exec_credentials

B クラスパスの拡張機能およびユーザー・クラスロード・メタデータ

- クラスパスの拡張機能

- jserverQuotedClassPathTermPrefix

- jserverURLPrefix

- jserverSpecialTokenPrefix

- JSERVER_CP

- JSERVER_SCHEMAc

- jserver:/CPの一般的な構文

- ユーザー・クラスロード・メタデータ

索引

例一覧

- 2-1 現行のクラスからのリゾルバの取得

- 2-2 コール側クラスからのリゾルバの取得

- 2-3 スキーマ名とクラス名の指定

- 2-4 オペレーティング・システム・リソースのクローズ

- 2-5 オペレーティング・システム・リソースの調整

- 2-6 オペレーティング・システム・リソースの正しい管理

- 3-1 デフォルト・サービスが定義されたlistener.oraの基本構成

- 6-1 簡単なJDBCストアド・プロシージャの公開

- 6-2 main()メソッドの公開

- 6-3 整数値を戻すメソッドの公開

- 6-4 引数の値を切り替えるメソッドの公開

- 6-5 パッケージのコール仕様

- 7-1 簡単なJDBCストアド・プロシージャ

- 7-2 フィボナッチ数列

- 7-3 データベース・トリガーからのJavaストアド・プロシージャのコール - I

- 7-4 データベース・トリガーからのJavaストアド・プロシージャのコール - II

- 10-1 パーミッションの付与

- 10-2 パーミッションの制限

- 10-3 PolicyTableパーミッションの付与

図一覧

- 1-1 クラスとインスタンス

- 1-2 Javaコンポーネント構造

- 1-3 Oracle DatabaseのJavaコンポーネント構造

- 1-4 クラス階層

- 1-5 2層クライアント/サーバー構成

- 1-6 ガベージ・コレクション

- 1-7 インタプリタとAccelerator

- 1-8 Oracle JVMの主要コンポーネント

- 2-1 各データベース・セッション内のJava環境

- 2-2 Oracle DatabaseへのJavaのロード

- 2-3 クラスの実行権限

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

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

- 2-6 JConsoleインタフェースの「Overview」タブ

- 2-7 JConsoleインタフェースの「Memory」タブ

- 2-8 JConsoleインタフェースの「Threads」タブ

- 2-9 JConsoleインタフェースの「Classes」タブ

- 2-10 MBeanの属性の表示

- 2-11 属性の値のグラフの表示

- 2-12 「MBeans」タブの複雑な属性の詳細の表示

- 2-13 JConsoleインタフェースの「MBeans」タブの「Operations」タブ

- 2-14 JConsoleインタフェースの「VM」タブ

- 2-15 OracleRuntime MBeanの「Attributes」タブ

- 2-16 OracleRuntime MBean

- 2-17 sessionsRunningJava操作

- 2-18 sessionDetailsBySID操作

- 2-19 「MBeans」タブの使用量のしきい値とコレクション使用量のしきい値の設定

- 2-20 使用済メモリーが使用量のしきい値を超えた場合のJConsoleインタフェースの「Memory」タブ

- 3-1 クライアント側スタブ・インタフェース

- 5-1 ストアド・プロシージャのコール

- 6-1 Javaメソッドのコール

- 8-1 発注書アプリケーションのスキーマ計画

- 9-1 Oracle JVMのメモリー・パラメータの構成

- 13-1 Webサービスからのデータベースのコール

- 13-2 データベース内からのWebサービスのコール

- 13-3 仮想表へのリクエスト結果の格納

- 13-4 Webサービスからのコール用のスタブの作成

表一覧

- 1-1 Oracle JVMの機能リスト

- 2-1 Javaのコードとクラスの説明

- 2-2 nameパラメータとoptionパラメータの定義

- 2-3 JAVA$OPTIONS表の例

- 2-4 ORAエラー

- 2-5 Javaファイルの説明

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

- 2-7 主なUSER_OBJECT列

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

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

- 2-10 JConsoleインタフェースの「Overview」タブのフィールドの説明

- 3-1 コマンドライン引数の概要

- 3-2 set_output_to_sqlの引数の概要

- 3-3 set_output_to_javaの引数の概要

- 6-1 有効なデータ型マッピング

- 10-1 事前定義のパーミッション

- 10-2 JServerPermissionの説明

- 10-3 SYSの初期のパーミッション

- 10-4 PUBLICのデフォルトのパーミッション

- 10-5 JAVAUSERPRIVのパーミッション

- 10-6 JAVASYSPRIVのパーミッション

- 10-7 JAVADEBUGPRIVのパーミッション

- 12-1 ojvmtcの引数の概要

- 12-2 loadjavaの引数の概要

- 12-3 dropjavaの引数の概要

- 12-4 ojvmjavaの引数の概要

- 12-5 ojvmjavaコマンドの共通オプション

- 12-6 javaの引数の概要

- 12-7 connectの引数の概要

- 12-8 runjavaの引数の概要

- 12-9 jdwpの引数の概要

はじめに

Javaは、プラットフォーム非依存性および自動記憶域管理の手法を提供するために適したオブジェクト指向プログラミング言語です。これを使用してアプリケーションとアプレットを作成できます。Oracle Databaseでは、Javaアプリケーションの開発およびデプロイをサポートしています。

この章の内容は、次のとおりです。

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

対象読者

このマニュアルは、Java開発者と非Java開発者の両方を対象にしています。Javaプログラミングの経験が浅いPL/SQL開発者の方は、Javaおよびオブジェクト指向の概念に関する概要を参照してください。このマニュアルでは、Java開発者とPL/SQL開発者の方々を対象に、次の項目について説明します。

- Javaの概念とデータベースの概念を融合する方法

- Javaストアド・プロシージャの開発、ロードおよび実行方法

- Oracle JVM

- データベース内でJavaオブジェクトを管理するために理解する必要があるデータベースの概念

- Oracle DatabaseとJavaのセキュリティ・ポリシー

このマニュアルは、読者にOracle Database、SQLおよびPL/SQLの知識があることを前提としています。また、Javaおよびオブジェクト指向プログラミングの知識も有用です。

ドキュメントのアクセシビリティについて

オラクル社のアクセシビリティへの取組みの詳細は、Oracle Accessibility ProgramのWebサイトhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=docaccを参照してください。

Oracleサポートへのアクセス

Oracleのお客様は、My Oracle Supportにアクセスして電子サポートを受けることができます。詳細は、http://www.oracle.com/pls/topic/lookup?ctx=acc&id=infoまたはhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs (聴覚障害者向け)を参照してください。

関連ドキュメント

詳細は、次のOracleドキュメントを参照してください。

- 『Oracle Database JDBC開発者ガイド』

- 『Oracle Database JPublisherユーザーズ・ガイド』

- 『Oracle Database SQLJ開発者ガイド』

- 『Oracle Database Net Services管理者ガイド』

- 『Oracle Database Advanced Securityガイド』

- 『Oracle Database開発ガイド』

表記規則

このマニュアルでは次の表記規則を使用します。

規則

意味

.
.
.

垂直の省略記号は、例に直接関連しない複数の行が省略されていることを示します。

. . .

文またはコマンドの中に、水平の省略記号がある場合は、例に直接関連しないコードの一部が省略されていることを示します。

太字

太字は、本文中で定義されている用語および用語集に記載されている用語を示します。

< >

山カッコは、ユーザーが入力する名前を示します。

[ ]

大カッコは、カッコ内の項目を任意に選択することを表します。

『Oracle Database Java開発者ガイド』のこのリリースでの変更点

この章の内容は次のとおりです。

- Oracle Database 12c リリース1 (12.1)の変更点

Oracle Database 12c リリース1 (12.1)での変更点

Oracle Database 12cリリース1 (12.1)の『Oracle Database Java開発者ガイド』での変更点は次のとおりです。

新機能

このリリースの新機能は次のとおりです。

- 複数のJDKのサポート
「複数のJDKのサポート」を参照してください。

- JNDIのサポート
第11章「JNDIに対するOracle JVMのネイティブ・サポート」を参照してください。

- デフォルトのjava.securityリソースのカスタマイズのサポート
「デフォルトのjava.securityリソースのカスタマイズ」を参照してください。

- ロギングのサポート
「Oracle JVMでのロギング」を参照してください。

- Runtime.execのセキュアな使用
「Oracle DatabaseでのRuntime.exec機能の使用」を参照してください。

- デバッグ機能の強化。
ブレークポイントおよびウォッチポイントを使用して、Javaストアド・プロシージャをデバッグできます。デバッグの詳細は、「Javaストアド・プロシージャのデバッグ」を参照してください。

1 Oracle DatabaseにおけるJavaの概要

Oracle Databaseでは、Javaアプリケーションの開発、格納およびデプロイがサポートされています。この章では、SQLデータと統合されたサーバー側アプリケーションの開発に習熟しているOracle PL/SQLの開発者を対象として、Java言語について説明します。これらの開発者は、Oracle Databaseのスケーラビリティおよびパフォーマンスを利用したJavaのサーバー側アプリケーションを開発できます。

この章の内容は、次のとおりです。

- Javaの概要

- Oracle DatabaseにおけるJavaの使用

- Oracle JVMの概要

- Oracle JVMの機能リスト

- Oracle JVMの主要コンポーネント

- OracleのJavaアプリケーション方針

- 専用モード・セッションのメモリー・モデル

Javaの概要

Javaは、優れたオブジェクト指向プログラミング言語として登場しました。Javaの重要な概念は次のとおりです。

- Java仮想マシン(JVM)。プラットフォームの独立性を確保するための基礎を提供します。

- 自動記憶域管理機能。例: ガベージ・コレクション。

- C言語の構文に類似した言語構文。

このような概念から、オブジェクト指向で、アプリケーション・プログラムを効率的に作成できる言語であるJavaが開発されました。

この項の内容は、次のとおりです。

- Javaおよびオブジェクト指向プログラミングの用語

- Java言語の主な機能

- Java仮想マシン

- Javaクラス階層

Javaおよびオブジェクト指向プログラミングの用語

次の用語は、Oracle Database環境におけるJavaアプリケーション開発でよく使用される用語です。

- クラス

- オブジェクト

- インタフェース

- カプセル化

- 継承

- ポリモフィズム

クラス

クラスの概念は、どのオブジェクト指向プログラミング言語でもサポートされています。表定義のように、クラスでは、共通の特性を持つオブジェクトのテンプレートが提供されます。各クラスで、次の項目を定義できます。

- フィールド
フィールドは、特定クラスの各オブジェクト(インスタンス)に存在する変数、または、グローバルですべてのインスタンスに共通な変数です。インスタンスのフィールドは、リレーショナル表の行の列に類似しています。クラスによって、フィールドと各フィールドの型が定義されます。

Javaでは、フィールドをstaticとして宣言できます。staticとして宣言されたクラスのフィールドはグローバルであり、そのクラスのすべてのインスタンスに共通です。Javaランタイムの特定のインスタンス内の静的フィールドに対して、特定の時点の値は1つのみです。staticとして宣言されないフィールドは、そのクラスの各インスタンス内で個別の値として作成されます。

public、private、protectedおよびデフォルト・アクセス修飾子では、アプリケーションのフィールドの範囲が定義されます。Java言語仕様(JLS)では、すべてのフィールドに対するデータの可視性規則が定義されます。可視性規則では、これらのフィールド内のデータにどのような場合にアクセスできるかが定義されます。

図1-1の例では、従業員識別子がprivateとして定義されており、これは、他のオブジェクトがこのフィールドに直接アクセスできないことを示しています。この例で、オブジェクトがidフィールドにアクセスするには、getId()メソッドをコールします。

- メソッド
メソッドは、クラスに関連付けられたプロシージャです。フィールドと同様に、メソッドをstaticとして宣言でき、この場合、グローバルにコールできます。メソッドをstaticとして宣言しない場合、そのメソッドはインスタンス・メソッドで、オブジェクトがクラスのインスタンスである場合のオブジェクト上の操作としてのみコールできることを示しています。

フィールドと同様に、メソッドは、public、private、protectedまたはデフォルト・アクセスとして宣言できます。この宣言では、メソッドをコールできる範囲が定義されます。

オブジェクト

Javaオブジェクトはクラスのインスタンスであり、リレーショナル表の行に類似しています。オブジェクトはデータ値の集まりで、クラスの非静的フィールド定義によって記述される個々の要素です。

図1-1に、2つのフィールドid(従業員識別子)とlastName(従業員の姓)、およびgetId()メソッドとsetId(String anId)メソッドで定義されているEmployeeクラスの例を示します。idフィールドはprivateであり、lastNameフィールド、getId()メソッドおよびsetId(String anId)メソッドはpublicです。

図1-1 クラスとインスタンス

インスタンスを作成すると、フィールドには、ある従業員にのみ関係する個人のプライベートな情報が格納されます。つまり、1つの従業員インスタンスに含まれる情報は、該当する特定の従業員のみが認識しています。図1-1の例は、Employeeクラスの2つのインスタンスを示しており、1つは従業員Smith用、もう1つはJones用です。各インスタンスには、個々の従業員に関連する情報が含まれています。

継承

継承は、オブジェクト指向プログラミング言語の重要な機能です。これによって、クラスは他のクラスのプロパティを含めることができます。プロパティを継承するクラスは子クラスまたはサブクラスと呼ばれ、プロパティの継承元のクラスは親クラスまたはスーパークラスと呼ばれます。この機能は、定義済コードの再利用にも役立ちます。

図1-1の例では、Employeeクラスのプロパティを継承するFullTimeEmployeeクラスを作成できます。継承されるプロパティは、スーパークラスの各フィールドおよびメソッドに対して宣言されている接続修飾子によって決まります。

インタフェース

Javaでは単一の継承のみがサポートされ、つまり、各クラスは、1つのクラスからのみフィールドおよびメソッドを継承できます。複数のソースからプロパティを継承する必要がある場合、Javaは複数継承の形式のインタフェースの概念を提供します。インタフェースはクラスに類似しています。ただし、メソッドのシグネチャのみが定義され、実装は定義されません。インタフェースで宣言されたメソッドはクラスで実装されます。1つのクラスで複数のインタフェースを実装すると、複数継承が行われます。

カプセル化

カプセル化は、データとメソッドを他から隠すオブジェクトの機能を示し、オブジェクト指向プログラミングの基本原理の1つです。Javaでは、クラスによって、フィールド(オブジェクトの状態を格納)およびメソッド(オブジェクトのアクションを定義)がカプセル化されます。カプセル化によって、再利用可能なプログラムを作成できます。また、publicと宣言されたオブジェクトの機能にのみアクセスを制限することもできます。その他のすべてのフィールドおよびメソッドはprivateであり、内部的なオブジェクト処理に使用できます。

図1-1の例では、idフィールドがprivateであり、これへのアクセスは、それを定義しているオブジェクトに制限されます。他のオブジェクトがこのフィールドにアクセスするには、getId()メソッドを使用します。カプセル化を使用すると、getId()メソッドをprivateとして宣言するか、またはgetId()メソッドを定義しないことによって、idフィールドへのアクセスを拒否できます。

ポリモフィズム

ポリモフィズムは、異なるオブジェクトが同じメッセージに対してそれぞれ異なる応答をするための機能です。オブジェクト指向プログラミング言語では、1つ以上のメソッドを同じ名称で定義できます。これらのメソッドは異なるアクションを実行し、異なる値を戻すことができます。

図1-1の例で、各種の従業員がそれぞれの給与累計で応答できるようにする必要があるとします。給与は、従業員の種類ごとに異なる方法で計算されます。

- フルタイム従業員は賞与の支払対象です。

- 適用対象従業員は時間外手当の支払対象です。

手続き型言語では、考えられるケースをそれぞれ定義して、次のようなswitch文を記述します。

switch: (employee.type)
{
case: Employee
return employee.salaryToDate;
case: FullTimeEmployee
return employee.salaryToDate + employee.bonusToDate
...
}

新しい種類の従業員を追加する場合は、switch文を更新する必要があります。また、データ構造を変更する場合は、その構造を使用するswitch文をすべて変更する必要があります。Javaなどのオブジェクト指向言語では、Employeeクラスで定義されていない情報がサブクラスに含まれている場合、EmployeeクラスのサブクラスごとにメソッドcompensationToDate()を実装できます。たとえば、適用対象従業員のcompensationToDate()メソッドを次のように実装します。

public float compensationToDate()
{
return (super.compensationToDate() + this.overtimeToDate());
}

フルタイム従業員の場合は、compensationToDate()メソッドを次のように実装できます。

public float compensationToDate()
{
return (super.compensationToDate() + this.bonusToDate());
}

メソッド名を共通して使用することで、従業員の種類を指定しなくても、異なるクラスのメソッドをコールして、結果を取得できます。フルタイム従業員とパートタイム従業員を処理するために特別なメソッドを記述する必要はありません。

また、Employeeからプロパティを継承しないContractorクラスを作成し、このクラスにcompensationToDate()メソッドを実装することもできます。給与累計の合計を計算するプログラムは、フルタイム、パートタイム、契約社員のいずれであるかに関係なく給与計算時に全従業員に対して反復処理し、従業員ごとにcompensationToDate()メソッドをコールして戻された値を合算します。メソッドのコール元が正常に動作することを認識した上で、個々のcompensationToDate()メソッドまたはクラスを安全に変更できます。

Java言語の主な機能

Java言語には、サーバー・アプリケーションの開発に最適な機能がいくつかあります。次の機能があります。

- 簡潔性
Javaでは、オブジェクト・モデルが一貫して規定されているため、サーバー・アプリケーションの作成で使用される他のほとんどの言語より単純です。大規模なクラス・ライブラリの標準セットは、あらゆるプラットフォームのJava開発者が強力なツールとして使用できます。

- 移植性
Javaはプラットフォーム間で移植可能です。Javaでは、プラットフォームに依存するコードを記述でき、複数のシステム間でシームレスに移植するプログラムも容易に作成できます。

関連項目:
「Java仮想マシン」

- 自動記憶域管理
JVMでは、プログラムの実行中にすべてのメモリー割当てと割当て解除が自動的に実行されます。Javaプログラマは、新規オブジェクトに対するメモリーの割当てや、参照されなくなったオブジェクトに対するメモリーの解放を明示的に行うことはできません。かわりに、これらの操作はJVMに依存して実行されます。メモリーの解放処理は、ガベージ・コレクションと呼ばれます。

- 強い型指定
フィールドを使用するには、そのフィールドの型を宣言する必要があります。Javaの強い型指定によって、JavaアプリケーションとPL/SQLアプリケーション間における言語間のコールに対する適切で安全なソリューションが提供され、JavaコールとSQLコールが同じアプリケーション内に統合されます。

- ポインタの不使用
Javaの構文はC言語に類似していますが、ダイレクト・ポインタやポインタ操作はサポートされていません。プリミティブ型以外のすべてのパラメータは、値ではなく参照で渡します。この結果、オブジェクト識別性が保持されます。Javaでは、ポインタへの低水準の直接アクセスはサポートされていないため、メモリーの破損やリークを防ぐことができます。

- 例外処理
Java例外はオブジェクトです。Javaでは、開発者が、特定のクラスでメソッドによってスローされる例外を宣言する必要があります。

- 柔軟なネームスペース
Javaでは、クラスが定義され、そのクラスがインターネットのドメインのネームスペースを模倣した階層構造に格納されます。Javaアプリケーションは分散でき、名前の衝突を回避できます。Java Naming and Directory Interface(JNDI)などのJava拡張機能によって、複数のネーム・サービスを統合するためのフレームワークが提供されます。Javaのネームスペース・アプローチは非常に柔軟であるため、Oracleは、JLSに完全に準拠して、クラス名を解決するスキーマの概念を組み込むことができます。

- セキュリティ
JavaバイトコードとJVM仕様の設計によって、Javaバイナリ・コードのセキュリティを組込みメカニズムで検証できます。Oracle DatabaseとともにインストールされるSecurityManagerのインスタンスでは、Oracle Databaseのセキュリティと組み合せることによって、Javaメソッドをコールできるユーザーが判断されます。

- リレーショナル・データベースへの接続性の標準
Java Database Connectivity(JDBC)およびSQLJを使用すると、Javaコードで、リレーショナル・データベース内のデータに対するアクセスおよび操作ができます。Oracleには、ベンダーに依存しない移植性のあるJavaコードでリレーショナル・データベースにアクセスできるようにするドライバが用意されています。

Java仮想マシン

Javaソースは、他の高水準のコンピュータ言語と同様に、低水準のマシン命令にコンパイルされます。各命令サイズが一律に1バイトであるため、Javaでは、これらの命令はバイトコードと呼ばれています。Cなど他のほとんどの言語は、IntelまたはHPプロセッサに固有の命令など、マシン固有の命令にコンパイルされます。

コンパイル時に、Javaコードは、Java仮想マシン(JVM)によって実行される、プラットフォームに依存しない標準のバイトコード・セットに変換されます。JVMは、Javaコードを実行する特定のプラットフォーム用に最適化された個別のプログラムです。

図1-2に、プラットフォームの独立性が、Javaによってどのように保持されるかを示します。各プラットフォームには、オペレーティング・システムに固有のJVMがインストールされています。Javaバイトコードは、JVMを介して、プラットフォームに依存する適切な処理へと解析されます。

図1-2 Javaコンポーネント構造

Javaアプリケーションの開発では、Java言語で記述された事前定義のコア・クラス・ライブラリを使用します。Javaコア・クラス・ライブラリは、一般的な機能を提供する各パッケージに論理的に分割されています。基本言語のサポートはjava.langパッケージによって、I/Oサポートはjava.ioパッケージによって、ネットワーク・アクセスはjava.netパッケージによってそれぞれ提供されます。JVMとコア・クラス・ライブラリによって提供されるプラットフォームでは、Javaプログラマは、Javaをサポートするすべてのオペレーティング・システムで正常に実行されるアプリケーションを開発できます。この概念は、「1回作成すれば、どこでも実行可能(write once, run anywhere)」というJavaの考え方を推進するものです。

図1-3は、OracleのJavaアプリケーションがJavaコア・クラス・ライブラリの上部に位置し、Javaコア・クラス・ライブラリがJVMの上部に位置していることを示しています。OracleのJavaサポート・システムはデータベース内に配置されているため、JVMはオペレーティング・システムと直接対話するかわりに、Oracle Databaseライブラリと対話します。

図1-3 Oracle DatabaseのJavaコンポーネント構造

JavaおよびJVMの詳細は、Java言語仕様(JLS)およびJVM仕様を参照してください。JLSで構文やセマンティクスが定義され、JVM仕様では、アプリケーションを実行するシステムに必要な下位レベルのアクションが定義されます。さらに、JVM実装には、VMの実装者が仕様に従ってコンパイルしたかどうかを判断するための互換性テスト一式があります。このテスト一式は、Java Compatibility Kit(JCK)と呼ばれます。Oracle JVM実装は、JCKに完全に準拠しています。総合的なJava方針の一環として、公に規定された標準と、その標準への準拠を検証する簡単な方法によって、ベンダーはすべてのプラットフォームでJavaのサポートを統一できます。

Javaクラス階層

Javaでは、クラスは大規模なクラス階層内で定義されます。階層の最上部にObjectクラスがあります。Javaのすべてのクラスは、スーパークラスの継承連鎖内をさかのぼる過程で、あるレベルのObjectクラスを継承しています。クラスBがクラスAを継承している場合、クラスBの各インスタンスには、クラスBに定義されたすべてのフィールドとクラスAに定義されたすべてのフィールドが含まれます。

図1-4は、一般的なJavaのクラス階層を示しています。FullTimeEmployeeクラスには、Employeeクラスで定義されたidフィールドおよびlastNameフィールドがあります。これは、Employeeクラスから継承されているためです。また、FullTimeEmployeeクラスでは、FullTimeEmployeeにのみ含まれる別のフィールドbonusが追加されます。

クラスBのインスタンスでは、クラスAまたはクラスBのいずれかで定義された任意のメソッドをコールできます。例では、FullTimeEmployeeインスタンスでコールできるメソッドは、FullTimeEmployeeでのみ定義されたメソッド、およびEmployeeクラスで定義されたメソッドです。

図1-4 クラス階層

クラスBのインスタンスは、クラスAのインスタンスのかわりに使用でき、継承は、コードの再利用性を改善するための、オブジェクト指向言語の別の強力な構成となります。動作と状態を定義するクラスを、階層内の適切な場所、しかもクラス・ライブラリの既存の機能を利用できる場所に作成できます。

Oracle DatabaseにおけるJavaの使用

Javaは豊富なセキュリティ機能を備えた安全な言語であるため、データベースでJavaアプリケーションを作成およびロードできます。Javaは、Javaコードが格納されているオペレーティング・システムの改ざんを防止するように開発されています。Cなど、一部の言語では、データベースにセキュリティ上の問題が発生する可能性があります。これに対してJavaは、その設計により、データベース内の使用にも堅牢な言語です。

Java言語は開発者にとって多数の利点がありますが、Javaサーバー・アプリケーションをサポートするJVMをスケーラブルな方法で実装するのは容易ではありません。この項では、次の問題について説明します。

- JavaとRDBMS: 堅牢な組合せ

- マルチスレッド

- メモリー領域管理

- フットプリント

- Oracle JVMのパフォーマンス

- 動的クラス・ロード

JavaとRDBMS: 堅牢な組合せ

Oracle Databaseでは、Javaアプリケーションに対して、複合問合せの実行や同一データの異なるビューでの表示をサポートする動的なデータ処理エンジンが提供されます。クライアントからの要求はすべてデータ問合せとして構成されて即時処理され、問合せ結果がすぐに生成されます。

JavaとOracle Databaseを組み合せることによって、ビジネス・ニーズの変化に応じて簡単に更新できるコンポーネントベースでネットワーク中心のアプリケーションを作成できます。また、アプリケーションおよびデータ・ストアを、デスクトップからインテリジェント・ネットワークやネットワーク型のサーバーに移動できます。さらに重要なのは、これらのアプリケーションおよびデータ・ストアに任意のクライアント・デバイスからアクセスできることです。

図1-5に、従来の2層クライアント/サーバー構成を示します。この構成では、クライアントは、PL/SQLストアド・プロシージャのコールと同様の方法でJavaストアド・プロシージャをコールします。また、この図では、Oracle Net Services Connection Managerが、多数のネットワーク接続を単一のデータベース接続に結合する方法も示されています。このようにして、Oracle Databaseでは多数の同時ユーザーがサポートされます。

図1-5 2層クライアント/サーバー構成

マルチスレッド

マルチスレッドは、Java言語の主要なスケーラビリティ機能の1つです。Java言語とクラス・ライブラリによって、他の多くの言語に比べてマルチスレッド・アプリケーションをJavaで簡単に作成できますが、依然としてどのような言語でも、信頼性が高くスケーラブルなマルチスレッド・コードを記述するのは困難な作業です。

Oracle Databaseサーバーは、多数のユーザーの作業を効率的にスケジュールします。Oracle JVMはOracle Databaseのセッション・アーキテクチャを利用して、多数のユーザーのJavaアプリケーションを同時に実行します。Oracle DatabaseではJLSとJCKに必要なJava言語レベルのスレッドがサポートされていますが、データベースの有効範囲内でスレッドを使用するとスケーラビリティは向上しません。データベースの埋込みのスケーラビリティを使用すると、マルチスレッドJavaサーバーを記述する必要がなくなります。

ユーザーのスケジューリングには、シングル・スレッドJavaアプリケーションを作成してOracle Databaseの機能を使用してください。データベースが各アプリケーション間の処理をスケジューリングするため、スレッドを管理しなくてもスケーラビリティが実現します。また、マルチスレッドJavaアプリケーションの作成も可能ですが、複数のJavaスレッドを使用してもサーバーのパフォーマンスは向上しません。

マルチスレッドで生じる問題の1つは、スレッドと自動記憶域管理またはガベージ・コレクションとの間の相互作用です。汎用JVMで実行されるガベージ・コレクタでは、どのJava言語スレッドが実行されているか、または基盤となるオペレーティング・システムでどのようにスケジュールされているかは認識されません。非Oracle DatabaseモデルとOracle JVMモデルの相違点は、次のとおりです。

- 非Oracle Databaseモデル
単一のユーザーが単一のJavaスレッドにマップされ、単一のガベージ・コレクタによって全ユーザーからのガベージがすべて管理されます。通常、存続期間やサイズの異なるオブジェクトの割当てと回収は、異なる技法で処理されます。アプリケーションが過度にマルチスレッド化されると、少なくともネイティブ・スレッド用のオペレーティング・システム・サポートに依存するようになるため、信頼性が低下したり、スケーラビリティが限定される可能性があります。この種の実装の場合、高水準のスケーラビリティは十分に実証されていません。

- Oracle JVMモデル
多数のユーザーがサーバーに接続して同じJavaコードを実行する場合も、各ユーザーは各自のJVMで独自のJavaコードを実行しているように感じます。Oracle JVMの役割は、オペレーティング・システムのプロセスとスレッド、およびOracle Databaseのスケーラブルなアプローチを利用することです。このアプローチによって、一度に複数のユーザーからガベージが収集されることがなくなるため、Oracle JVMのガベージ・コレクタの信頼性と効率が向上します。

関連項目:
「Oracle Databaseのスレッド」

メモリー領域管理

ガベージ・コレクションはJavaの自動記憶域管理機能の主要な機能であり、Java開発者はメモリーの割当てと解放を明示的に行う必要がなくなります。そのため、CやC++のプログラムで一般に検出されるメモリー・リークの大きな原因がなくなります。ただし、ガベージ・コレクションはプログラムの実行スピードとフットプリントのオーバーヘッドに影響を与えます。

ガベージ・コレクションは、高スケーラブルで高速なJavaプラットフォームを提供しようとするJVM開発者に対する1つの課題です。Oracle JVMは、このような課題に次の方法で対応します。

- Oracle JVMでは、複数のユーザーを効率的に管理できるOracle Databaseのスケジューリング機能が使用されます。

- ガベージ・コレクションは単一セッション内の単一ユーザーを対象とするため、複数ユーザーに対しても一貫して実行されます。Oracle JVMの場合、ユーザー数が増加してもメモリー・マネージャの作業の負荷や複雑さは変わらないため、その点において有利です。メモリー・マネージャは単一セッション内でオブジェクトの割当てと回収を実行し、通常はこれが単一ユーザーのアクティビティに変換されます。

- Oracle JVMでは、使用するメモリーのタイプに応じて異なるガベージ・コレクションの技法が使用されます。これらの技法によって、効率が向上し、オーバーヘッドが低減します。

2種類のメモリー領域は、コール領域とセッション領域です。

メモリー領域

説明

コール領域

高速でコストの低いメモリーです。主にコール期間中に存在します。コール・メモリー領域は新規セグメントと旧セグメントに分割されます。新規オブジェクトはすべて新規メモリー内に作成されます。数回のスキャベンジ後も存在し続けているオブジェクトは、旧メモリーに移動されます。

セッション領域

コストの高いパフォーマンス重視のメモリーです。主にセッション期間中に存在します。コール存続期間より長い期間存在するすべてのstaticフィールドとオブジェクトは、この領域に存在します。

図1-6は、ガベージ・コレクタによって実行される様々なアクションを示しています。

図1-6 ガベージ・コレクション

Oracle JVM内のガベージ・コレクション・アルゴリズムは、次のルールを遵守します。

1. 新規オブジェクトは新規コール領域内に作成されます。

2. スキャベンジは既定の間隔で行われます。プログラマによっては、オブジェクトを短期間のみ頻繁に作成する場合があります。このようなタイプのオブジェクトは、新規コール領域内に作成され、すぐにガベージ・コレクションされます。これはスキャベンジと呼ばれます。

3. スキャベンジを数回繰り返した後も存在し続けているオブジェクトは、しばらくの間存在する可能性のあるオブジェクトとみなされます。これらのオブジェクトは、新規コール領域から旧コール領域に移動されます。移動中にも圧縮が行われます。旧コール領域はスキャベンジ(ガベージ・コレクション)される回数が少ないため、パフォーマンスが向上します。

4. コール終了時に、コール後も存在するオブジェクトはセッション領域に移動されます。

図1-6は、前述の説明の手順を示しています。このアプローチでは、オブジェクトの種類や存続期間にあわせて、効率的な割当と回収の仕組みが適用されます。たとえば、新規オブジェクトは、迅速な割当とアクセスを目的として設計された、高速でコストの低いコール・メモリーに割り当てられます。Java staticフィールドで保持されるオブジェクトは、より貴重でコストの高いセッション領域に移行されます。

フットプリント

Javaプログラムの実行によるフットプリントは、次の様々な要因の影響を受けます。

- プログラムのサイズ
プログラムのサイズは、クラス数、メソッド数およびそれらのコードの量によって決まります。

- プログラムの複雑さ
プログラムの複雑さは、プログラム自体ではなく、プログラムの実行時にOracle JVMで使用されるコア・クラス・ライブラリの数によって決まります。

- JVMが使用する領域の量
JVMが使用する領域の量は、JVMが割り当てるオブジェクトの数とサイズ、および複数コール間で保持する必要のあるオブジェクトの数によって決まります。

- ガベージ・コレクタとメモリー・マネージャが、プログラムの実行の要求を処理する能力
ほとんどの場合、この能力は決定要因ではありません。オブジェクトの割当て速度および他のオブジェクトによって保持される方法が、この要因の重要度に影響を与えます。

スケーラビリティの観点から、複数のクライアントを同時にサポートするには、ユーザー当たりのセッション・フットプリントを最小限に抑えることが重要です。Oracle JVMでは、Javaバイトコードなど、ユーザー用のすべての読取り専用データを共有メモリーに格納することで、ユーザー当たりのセッション・フットプリントを最小限に抑えます。ユーザー・セッションのフットプリントが大きくならないように、コールとセッションのメモリーに対して、適切なガベージ・コレクション・アルゴリズムが適用されます。Oracle JVMでは、ユーザーのセッション・メモリーのメンテナンスに、次の種類のガベージ・コレクション・アルゴリズムが使用されます。

- ジェネレーション・スキャベンジ: 存続期間の短いオブジェクトの場合

- マーク/レイジー・スイープ・コレクション: 単一コールの間に存在するオブジェクトの場合

- コレクタのコピー: 存続期間の長いオブジェクト、つまり、セッション内の複数コールにわたって存在するオブジェクトの場合

Oracle JVMのパフォーマンス

Oracle JVMのパフォーマンスは、標準のHotSpotと同様に革新的なJust-In-Timeコンパイラを組み込むことによって向上します。プラットフォームに依存しないJavaバイトコードはJVMの上部で実行され、そのJVMは特定のハードウェア・プラットフォームと対話します。ソフトウェア内でレベルを追加すると、パフォーマンスが低下します。Javaでは、バイトコードを解析するために仲介部分を通過する必要があるため、Javaアプリケーションには、C言語のようなプラットフォームに依存する言語を使用して開発されたアプリケーションと比較して、ある程度の非効率性が伴います。この問題に対処するために、複数のJVMサプライヤがネイティブ・コンパイラを作成しています。ネイティブ・コンパイラによって、Javaバイトコードはプラットフォームに依存するネイティブ・コードに変換され、その結果、インタプリタのステップが不要になり、パフォーマンスが向上します。

次の表に、ネイティブ・コンパイルの2つの方法を示します。

コンパイラ

説明

Just-In-Time(JIT)コンパイル

JITコンパイラは、実行時にJavaバイトコードをプラットフォーム固有(ネイティブ)のマシン・コードに迅速にコンパイルします。これらのコンパイラでは、プラットフォームで実行される実行可能ファイルは生成されません。かわりに、変換後に直接実行されるプラットフォームに依存するコードがJavaバイトコードから作成されます。JITコンパイラは、頻繁に実行され、Cなどの他言語で開発されたコードとほぼ同じ速度で実行されるJavaコードに対して使用してください。

Ahead-of-Timeコンパイル

このコンパイルでは、実行前にJavaバイトコードがプラットフォームに依存しないCコードに変換されます。次に、標準的なCコンパイラで、Cコードがターゲット・プラットフォーム用の実行可能ファイルにコンパイルされます。この方法は、あまり変更されないJavaアプリケーションに適しています。この方法は、最近のCコンパイラで採用されている成熟した効率的なプラットフォーム固有のコンパイル技術を利用しています。

Oracle Databaseは、Just-In-Time (JIT)コンパイルを使用して、JDBCコードなどのコアなJavaクラス・ライブラリをネイティブにコンパイル済の形式で配布しています。JITコンパイラは、プラグインのサポートがなくても有効で、これは、Oracleがサポートしているすべてのプラットフォームで適用できます。

関連項目:
Oracle JVMのJust-In-Time(JIT)コンパイラ

図1-7に示すように、ネイティブにコンパイルされたコードは、解析されるコードに比較して最高で10倍速く実行されます。この結果、プログラムで使用するネイティブ・コードが多いほど、実行速度が速くなります。

図1-7 インタプリタとAccelerator

動的クラス・ロード

Javaのもう1つの強力な機能は、動的クラス・ロードです。クラス・ローダーは、クラスをディスクからロードし、解析に必要なJVM固有のメモリー構造に格納します。また、クラスをCLASSPATH内で検索し、プログラムの実行中に使用される場合にのみロードします。この方法はアプレットに適していますが、サーバー環境では次の問題があります。

問題

説明

解決策

予測可能性

クラス・ロード操作は、プログラムの初回実行時に重大なペナルティを伴います。単純なプログラムの場合でも、Oracle JVMによって、そのニーズをサポートするための多数のコア・クラスがロードされる可能性があります。ロードされるクラスの数は、プログラマが簡単に予測または判断することはできません。

Oracle JVMは、他のJVMと同様に、クラスを動的にロードします。1回のクラス・ロードの速度は同じです。ただし、クラスは共有メモリーにロードされるため、そのクラスの他のユーザーはクラスを再ロードする必要はなく、同じ事前ロード・クラスを使用します。

信頼性

動的クラス・ロードの利点は、プログラムの更新がサポートされることです。たとえば、サーバー上でクラスを更新すると、プログラムをダウンロードして動的にロードするクライアントでは、次回そのプログラムを使用するときに更新されたことがわかります。サーバー・プログラムでは、信頼性が重視されます。開発者は、各クライアントが特定のプログラム構成を実行していることを認識する必要があります。意図していない一部のクラスがクライアントによって不注意にロードされないようにしてください。

Oracle Databaseでは、アップロードおよび解決操作が、実行時のクラス・ロード操作と分離されます。開発したJavaコードをサーバーにアップロードするには、loadjavaツールを使用します。CLASSPATHを使用するかわりに、インストール時にリゾルバを指定します。リゾルバはCLASSPATHに類似していますが、クラスが存在するスキーマを指定できます。このように解決操作をクラス・ロードから分離することで、ユーザーがどのプログラムを実行しているかを常に把握できます。
関連項目: 第12章「スキーマ・オブジェクトおよびOracle JVMユーティリティ」

Oracle JVMの概要

Oracle JVMは、Pure Javaアプリケーションを実行する標準的なJava互換環境です。これは、標準のJLSおよびJVMの仕様と互換性があります。標準Javaバイナリ形式および標準Java APIをサポートしています。また、Oracle Databaseは、実行時の動的クラス・ロードなど、標準のJava言語のセマンティクスに準拠しています。

Oracle DatabaseにおけるJavaでは、次の用語が使用されます。

- セッション
Oracle DatabaseのJava環境で使用しているセッションは、Oracle Databaseで標準的に使用されるセッションと同じ意味です。通常、セッションとは、1人のユーザーがサーバーに接続している期間で区切られます(例外もあります)。Javaコードをコールするユーザーは、サーバーでセッションを確立する必要があります。

- コール
ユーザーがセッション内でJavaコードを実行する場合、これをコールと呼びます。コールは次のような様々な方法で開始できます。

- SQLクライアント・プログラムによるJavaストアド・プロシージャの実行。

- トリガーによるJavaストアド・プロシージャの実行。

- PL/SQLプログラムからのJavaコードのコール。

定義されているいずれの場合も、コールが開始され、Java、SQLまたはPL/SQLコードのいずれかの組合せが実行されて完了し、コールが終了します。

注意:
セッションとコールの概念は、Oracle Databaseの使用時に必ず適用されます。

他のJava環境とは異なり、Oracle JVMは、Oracle Database内に埋め込まれているため、多くの新しい概念が導入されています。この項では、Oracle JVMと一般的なクライアントJVMとの重要な相違点をいくつか説明します。

- プロセス領域

- Javaセッションの初期化、期間およびエントリ・ポイント

- GUI

- IDE

プロセス領域

標準的なJava環境では、コマンドラインで次のコマンドを発行することで、インタプリタを介してJavaアプリケーションを実行します。このコマンドで、classnameは、JVMで最初に解析するクラスの名称です。

java classname

Oracle JVMを使用する際には、アプリケーションをデータベースにロードし、インタフェースを公開してから、データベース・セッション内でアプリケーションを実行する必要があります。データベース・セッションは、Oracle JVMが実行している環境であり、そのため、標準的なクライアントJVMが実行しているオペレーティング・システム・プロセスと類似しています。

関連項目:
Javaアプリケーションのロード、公開および実行の詳細は、第2章「Oracle DatabaseでのJavaアプリケーション」を参照してください。

Javaセッションの初期化、期間およびエントリ・ポイント

標準的なクライアントベースのJavaアプリケーションでは、トップレベルのメソッド(public static void main(String args[]))が1つ宣言されます。このメソッドは1回実行され、Java仮想マシンのインスタンス化はそのコールの期間中、続きます。しかし、Oracle Javaアプリケーションは、単一のトップレベルの主なエントリ・ポイントに制限されず、Oracle JVMのインスタンス化の期間は、単一のコールおよびこのエントリ・ポイントからのコールの終了によって決定されません。各クライアントは、セッションを開始し、トップレベルのエントリ・ポイント経由でサーバー側の論理モジュールをコールし、セッションを終了します。同じJVMインスタンスは、セッションの期間全体に設定されたままであるため、静的変数の値などのデータ状態は、トップレベルの複数のエントリ・ポイントへの複数のコールにわたって使用できます。

データベースにロードおよび公開されたクラス定義は、通常、そのデータベース内のすべてのセッションで使用可能です。指定したセッション内のJVMインスタンス、Javaデータ・オブジェクト、そのJVMインスタンス内のグローバル・フィールド値は、セッションに対してプライベートです。このデータは、セッションの期間中存在し、そのセッションの存続期間内の複数のコールによって使用できます。しかし、このデータは他のセッションでは参照できず、データはどの方法でも他のセッションと共有できません。これは、標準的なクライアントJavaアプリケーションの、mainメソッドの離れた起動で同じクラス定義を共有する方法に類似していますが、これらの起動中に作成および使用されるデータは切り離されています。

GUI

サーバーではGUIは提供されませんが、GUIを動作させるロジックが提供されます。Oracle JVMでは、Java Abstract Window Toolkit (AWT)のヘッドレス・モードのみがサポートされます。サーバー上でGUIを実体化しようとしないかぎり、すべてのJava AWTクラスをサーバー環境で使用でき、プログラムでJava AWTの機能を利用できます。

関連項目:
「サーバー上のユーザー・インタフェース」

IDE

Oracle JVMは、Javaアプリケーションの開発ではなく、デプロイメント指向です。アプリケーションの作成とテストは、Oracle JDeveloperなどの任意の統合開発環境(IDE)で行い、その後、クライアントによるアクセスおよび実行用にデータベース内にデプロイできます。

関連項目:
「開発ツール」

Javaのバイナリ互換性によって、任意のIDEで作成したJavaクラス・ファイルをサーバーにアップロードできます。Javaソース・ファイルをデータベースに移動する必要はありません。かわりに、強力なクライアント側のIDEを使用して、サーバー上にデプロイしたJavaアプリケーションをメンテナンスできます。

Oracle JVMの機能リスト

表1-1に、Oracle JVMの機能と、その機能が最初にサポートされたバージョンを示します。

表1-1 Oracle JVMの機能リスト

機能

サポートされた最初のOracle JVMリリース

loadjavaのURLサポート

11.1

dropjavaを使用したリストベースの操作のサポート

11.1

ojvmtcツール

11.1

Runjavaコマンドライン・インタフェース(JDKに類似のインタフェース)

11.1

データベース常駐JAR

11.1

ユーザー・クラスロード・クラスのメタデータの共有サポート

11.1

Javaセッションの状態に使用する2層の期間のサポート

11.1

デフォルトのサービス機能

11.1

Just-In-Time(JIT)コンパイラ

11.1

Internet Protocol Version 6(IPv6)のサポート

11.2

JDK 6のサポート

12.1

JDK 7のサポート

12.1

Oracle JVMの主要コンポーネント

この項では、Oracle JVMの主要コンポーネントおよびそれらが提供する機能の一部を簡単に説明します。

Oracle JVMは、Javaアプリケーションを実行するための、Java 2との完全互換の環境です。これは、そのメモリー・ヒープを共有し、リレーショナル・データに直接アクセスすることで、データベース・カーネルと同じプロセス領域およびアドレス領域で実行されます。この設計によりメモリーの使用を最適化して、スループットを向上させます。

Oracle JVMでは、Javaオブジェクト用のランタイム環境が提供されます。Javaのデータ構造、メソッド・ディスパッチ、例外処理および言語レベル・スレッドを完全にサポートします。また、java.lang、java.io、java.net、java.mathおよびjava.utilなど、すべてのコアJavaクラス・ライブラリもサポートしています。

図1-8に、Oracle JVMの主要コンポーネントを示します。

図1-8 Oracle JVMの主要コンポーネント

Oracle JVMは、標準のJavaネームスペースをデータベース・スキーマに埋め込みます。この機能によって、Javaプログラムで、企業のOracle Databaseやアプリケーション・サーバーに格納されているJavaオブジェクトにアクセスできます。

また、Oracle JVMは、データベースのスケーラブルな共有メモリー・アーキテクチャと緊密に統合されています。Javaプログラムでは、ユーザーの介入なしで、コール、セッションおよびオブジェクトの存続期間が効率的に使用されます。この結果、Oracle JVMおよび中間層のJavaビジネス・オブジェクトは、それらが長く存続するセッションの場合でも適切に調整できます。

次の項では、Oracle JVMの一部のコンポーネント、およびJDBCドライバとSQLJトランスレータの概要について説明します。

- ライブラリ・マネージャ

- コンパイラ

- インタプリタ

- クラス・ローダー

- 検証機能

- サーバー側JDBC内部ドライバ

- サーバー側SQLJトランスレータ

- システム・クラス

関連項目:
「メモリー領域管理」および「Oracle JVMのパフォーマンス」

ライブラリ・マネージャ

JavaクラスをOracle Databaseに格納するには、SQLのCREATE JAVA文を使用してその作業を実行する、loadjavaコマンドライン・ツールを使用します。CREATE JAVA {SOURCE | CLASS | RESOURCE}文によってコールされると、ライブラリ・マネージャはJavaのソース、クラスまたはリソース・ファイルをデータベースにロードします。これらのJavaスキーマ・オブジェクトは直接アクセスされることはなく、Oracle JVMのみが使用します。

コンパイラ

Oracle JVMには、標準のJavaコンパイラが組み込まれています。CREATE JAVA SOURCE文が実行されると、Javaコンパイラは、Javaソース・ファイルをバイトコードと呼ばれるアーキテクチャに依存しない1バイトの命令に変換します。各バイトコードは、命令コードとそれに続くオペランドで構成されています。結果として、Javaの標準に完全に準拠したJavaクラス・ファイルが生成され、実行時にインタプリタに送信されます。

インタプリタ

Javaプログラムを実行するために、Oracle JVMには標準Java 2のバイトコード・インタプリタが組み込まれています。インタプリタとそれに関連するJavaランタイム・システムによって、標準のJavaクラス・ファイルが実行されます。ランタイム・システムでは、ネイティブ・メソッド、およびホスト環境からのコールとホスト環境へのコールがサポートされます。

注意:
パフォーマンスを向上させるためにJavaコードをコンパイルすることもできます。Oracle JVMでは、ネイティブにコンパイルされたコアなJavaクラス・ライブラリ、SQLJトランスレータおよびJDBCドライバが使用されます。

クラス・ローダー

ランタイム・システムからの要求に応答して、Javaクラス・ローダーは、データベースに格納されているJavaクラスを検索、ロードおよび初期化します。クラス・ローダーはクラスを読み取り、そのクラスの実行に必要なデータ構造を生成します。不変のデータやメタデータは、初期化が1回の共有メモリーにロードされます。この結果、セッションごとに必要なメモリー量が低下します。クラス・ローダーは、必要に応じて外部参照を解決しようとします。また、ソース・ファイルが使用可能な場合、Javaクラス・ファイルを再コンパイルする必要があるときは、Javaコンパイラを自動的にコールします。

検証機能

Javaクラス・ファイルは、完全に移植可能で、明確に定義された形式に準拠しています。検証機能は、プログラム・フローを改ざんしたり、アクセス制限に違反する恐れのあるにせのJavaクラス・ファイルが誤って使用されるのを防止します。OracleのセキュリティとJavaのセキュリティが検証機能と連携することによって、ユーザーのアプリケーションとデータが保護されます。

サーバー側JDBC内部ドライバ

JDBCは標準であり、ベンダーに依存しないリレーショナル・データへのアクセスを提供するJavaクラスのセットを定義します。ODBCおよびX/Open SQL Call Level Interface(CLI)をモデルにしたJDBCクラスは、複数のデータベースへの同時接続、トランザクション管理、単純な問合せ、ストアド・プロシージャのコール、LONG型の列データへのストリーム形式のアクセスなどの標準的な機能を提供します。

特別にチューニングされたJDBCドライバは、下位レベルのエントリ・ポイントを使用してOracle Database内で直接実行され、Javaストアド・プロシージャからOracleデータへの高速アクセスを提供します。サーバー側JDBC内部ドライバは、標準のJDBC仕様に完全に準拠しています。JDBCドライバは、データベースと緊密に統合されているため、Oracle固有のデータ型、グローバリゼーション・キャラクタ・セットおよびストアド・プロシージャをサポートしています。また、クライアント側とサーバー側のJDBC APIが同じであるため、アプリケーションの分割を容易に行うことができます。

サーバー側SQLJトランスレータ

SQLJを使用すると、SQL文をJavaプログラムに埋め込むことができます。これはJDBCよりも簡潔であり、静的な分析と型チェックに対してすぐに応答できるようになります。それ自体がJavaプログラムであるSQLJプリプロセッサは、SQLJ句が埋め込まれているJavaソース・ファイルを入力として取得します。次に、SQLJ句を、指定したSQL文を実装するJavaクラス定義に変換します。Java型システムによって、これらのクラスのオブジェクトは正しい引数でコールされることが保証されます。

高度に最適化されたSQLJトランスレータはデータベース内で直接実行され、サーバー側JDBC内部ドライバを使用して、Oracleデータへのランタイム・アクセスを提供します。SQLJフォームには、問合せ、データ操作言語(DML)文、データ定義言語(DDL)文、トランザクション制御文、およびストアド・プロシージャのコールを組み込むことができます。クライアント側とサーバー側のSQLJ APIが同じであるため、アプリケーションの分割を容易に行うことができます。

システム・クラス

Oracle Database環境でJava実装の重要な部分を構成するクラスのセットはシステム・クラスと呼ばれます。これらのクラスは、SYSスキーマで定義され、すべてのユーザーについてPUBLICシノニムごとにエクスポートされます。いずれかのシステム・クラスと同じ名前を持つクラスは、SYSスキーマ以外のスキーマで定義できます脚注1。ただし、その代替クラスが、他のシステム・クラスまたはJava仮想マシンの基本的な実装に存在する、そのクラスのセマンティクスの条件に違反して動作することがあるため、これは適切な操作ではありません。オラクル社では、この操作は絶対にお薦めしません。

OracleのJavaアプリケーション方針

Oracleは、エンタープライズ・アプリケーションの開発者に、Javaアプリケーションの作成、デプロイおよび管理のためのエンドツーエンドのJavaソリューションを提供します。この総合的なソリューションは、クライアント側とサーバー側のプログラム・インタフェース、Java開発をサポートするツール、Oracle Databaseと統合されたJVMで構成されています。これらの製品はすべて、Java標準と完全に互換性があります。この項の内容は、次のとおりです。

- データベース・アプリケーション開発におけるJava

- Javaプログラミング環境

- Javaストアド・プロシージャ

- PL/SQLの統合とOracle RDBMSの機能

- 開発ツール

- Internet Protocol Version 6のサポート

- 複数のJDKのサポート

データベース・アプリケーション開発におけるJava

データベース・アプリケーション開発におけるJavaの最も重要な機能は、次のとおりです。

- JDBCおよびSQLJレベルの対称型データ・アクセスに対する、Java2 Platform, Standard Edition(J2SE)アプリケーションの柔軟な分割の提供。

- SQLとJava2 Platform, Enterprise Edition(J2EE)のブリッジ。次の方法があります。

- JSPやサーブレットなどのWebコンポーネントのコール

- SQLとWebサービスのブリッジ

- Webサービスのコール

- ERP統合ハブとしてのOracle JVMの使用

- キャッシュの無効化

Javaプログラミング環境

Javaプログラミング環境には、Oracle JVM以外に次のコンポーネントがあります。

- PL/SQLに等価および相当するJavaストアド・プロシージャ。Javaストアド・プロシージャは、PL/SQLと緊密に統合されています。PL/SQLパッケージからJavaストアド・プロシージャをコールでき、Javaストアド・プロシージャからPL/SQLプロシージャをコールできます。

- SQLデータにアクセスするためのJDBCおよびSQLJプログラミング・インタフェース。

- クラスの開発、ロードおよび管理に役立つツールとスクリプト。

どのような場合にどのJava APIを使用するかを判断するには、次の表を参考にしてください。

必要な機能のタイプ

使用するJava API

トリガーなどのJavaプロシージャをSQLからコールする場合。

Javaストアド・プロシージャ

既知の列名を持つ既知の表にある静的で単純なSQL文を、Javaオブジェクトからコールする場合。

SQLJ

動的な複合SQL文をJavaオブジェクトからコールする場合。

JDBC

Javaストアド・プロシージャ

Javaストアド・プロシージャは、PL/SQLストアド・プロシージャと同様に、サーバーで作成およびデプロイされ、サーバーで実行されるJavaプログラムです。Javaストアド・プロシージャを起動するには、SQL*Plusなどの製品から直接起動するか、またはトリガーを使用して間接的に起動します。また、OCIやPRO*などのすべてのOracle Netクライアント、あるいはJDBCまたはSQLJからアクセスできます。

関連項目:
第5章「Javaストアド・プロシージャの開発」

また、Javaを使用して、PL/SQLに依存しない強力なサーバー側プログラムを開発することもできます。Oracle Databaseには、標準Javaプログラミング言語および完全準拠のJVMの完全な実装が用意されています。

PL/SQLの統合とOracle RDBMSの機能

既存のPL/SQLプログラムをJavaからコールしたり、JavaプログラムをPL/SQLからコールできます。このソリューションでは、PL/SQLおよびJavaのコードを保護して利用しながら、Javaベースのインターネット・コンピューティングの利点と機会を活用できます。

Oracle Databaseでは、SQLデータにアクセスするためのJava APIが、JDBCとSQLJの2種類提供されています。両方のAPIをクライアントとサーバーで使用できます。このため、コードを変更せずに、クライアントとサーバーにアプリケーションをデプロイできます。

次の各項では、Oracle Databaseで提供されるJava APIおよびJPublisherのツールについて説明します。

- JDBCドライバ

- SQLJ

- JPublisher

JDBCドライバ

JDBCは、ユーザーがデータベースに接続してSQL文を実行し、データベースに問合せできるようにするデータベース・アクセス・プロトコルです。コアなJavaクラス・ライブラリに用意されているJDBC APIは、java.sqlとjavax.sqlです。ただし、JDBCは、ベンダーが特定のデータベースを必要に応じて特化するためのドライバを提供できるように設計されています。Oracleには、次のJDBCドライバが個別に用意されています。

ドライバ

説明

JDBC Thinドライバ

JDBC Thinドライバを使用すると、Oracle SQLのデータにアクセスするPure Javaのアプリケーションおよびアプレットを作成できます。JDBC Thinドライバは、他のJavaアプレットと同様にWebページから動的にダウンロードできるため、Webベースのアプリケーションとアプレットに特に適しています。

JDBC OCIドライバ

JDBC OCIドライバは、クライアントまたは中間層にあるOracle固有のネイティブ・コード(つまり非Javaコード)およびライブラリにアクセスします。JDBC Thinドライバと比較してパフォーマンスが向上しますが、サイズが極端に大きくなること、およびクライアント側でインストールが必要であるという問題があります。

サーバー側JDBC内部ドライバ

Oracle Databaseは、Javaコードがサーバー上で実行される場合に、サーバー側内部ドライバを使用します。これにより、サーバーのOracle JVM内で実行中のJavaアプリケーションは、ローカルに定義されたデータ(つまり、同じシステムの同じプロセスにあるデータ)にJDBCを使用してアクセスできます。また、基礎となるOracle RDBMSライブラリを直接使用できるため、パフォーマンスが向上し、JavaコードとSQLデータの間にネットワーク接続が介入することによるオーバーヘッドは発生しません。Oracle Databaseでは、サーバー上で同じJava-SQLインタフェースがサポートされるため、デプロイ時にコードの再処理を必要としません。

関連項目:

- 「データベースでのSQLJおよびJDBCとJavaの併用」

- 『Oracle Database JDBC開発者ガイド』

SQLJ

オラクル社は、IBM社、Tandem社、Sybase社などの他のベンダーと共同で作業し、SQL文をJavaプログラムに埋め込む、SQLJと呼ばれる標準方式を開発しました。この結果、JDBCより単純で生産性の高いプログラミングAPIに関して、新しい標準ANSI x.3.135.10-1998が作成されました。ユーザーはこの高水準のAPIに対するアプリケーションを作成し、プリプロセッサを使用して、そのプログラムをJDBCコールが含まれる標準のJavaソースに変換します。実行時に、プログラムは、標準のJDBCドライバを使用してマルチベンダーのデータベースと通信できます。

SQLJは、Javaからデータベースにアクセスするクライアント・サイド・アプリケーションと中間層アプリケーションの両方を開発するための、単純ですが強力な方法を提供します。Oracle Database 12c環境内では、ストアド・プロシージャ、トリガーおよびメソッドでSQLJを使用できます。また、SQLJプログラムはJDBCと結合できます。

SQLJトランスレータは、Javaソース・コードの埋込みSQLをJDBCベースのPure Javaコードに変換するJavaプログラムです。Oracle Database 12cでは完全なJava環境が提供されているため、サーバーで実行されるSQLJプログラムをクライアントでコンパイルすることはできません。かわりに、サーバーで直接コンパイルできます。Oracle Databaseはインターネット標準に準拠しているため、必要に応じて開発スタイルを選択できます。

関連項目:

- 「データベースでのSQLJおよびJDBCとJavaの併用」

- 『Oracle Database SQLJ開発者ガイド』

JPublisher

JPublisherは、既存のOracleリレーショナル・データベース表にアクセスするJavaプログラムを作成するための、使いやすい便利なツールを提供します。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

開発ツール

JavaをOracle Databaseに導入することによって、複数のJava IDEを使用できるようになります。Oracle Databaseは、Javaの標準と仕様およびオープン・インターネットの標準とプロトコルに完全に準拠しているため、作成したJavaのプログラムは、Oracle Database上にデプロイしたときに正常に動作することが保証されます。Oracleには、Javaで作成されているツールやユーティリティが多数あり、Javaサーバー・アプリケーションの開発およびデプロイメントを容易にします。また、Oracle JDeveloper(Oracleが提供するJava IDE)には、Javaストアド・プロシージャとEJBのデプロイメントを容易にするために特別に設計された機能が多数あります。JDeveloperは、http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.htmlからダウンロードできます。

Internet Protocol Version 6のサポート

Oracle Database 11gリリース2から、Oracle JVMでは、URLのInternet Protocol Version 6 (IPv6)アドレスと、IPv6アドレスに解決されるデータベース内のJavaコードのマシン名をサポートしています。IPv6は、Internet Engineering Task Force(IETF)で設計された新しいネットワーク層プロトコルで、Internet Protocolの現行バージョンのInternet Protocol Version 4(IPv4)に代わるものです。IPv6の主な利点として、128ビット・アドレスの使用から導出される大容量のアドレス空間があります。また、ルーティング、ネットワークの自動構成、セキュリティ、サービスの質などの分野でIPv4が改良されています。

次のシステム・プロパティを使用すると、IPv6のプリファレンスを構成できます。

java.net.preferIPv4Stack

IPv6がオペレーティング・システムで使用可能な場合、基礎となるネイティブ・ソケットはIPv6ソケットになります。このため、JavaアプリケーションはIPv4とIPv6の両方のホストに接続して、これらのホストからの接続を受け入れることができます。アプリケーションでIPv4ソケットのみを使用するようにプリファレンスが設定されている場合、このプロパティをtrueに設定できます。プロパティをtrueに設定すると、アプリケーションはIPv6のホストと通信できなくなります。

java.net.preferIPv6Addresses

IPv6がオペレーティング・システムで使用可能な場合でも、アドレスは下位互換性があるためIPv4にマップされます。たとえば、IPv4サービスへのアクセスのみに依存するアプリケーションでは、このようなマッピングによる利点があります。IPv4アドレス経由でIPv6アドレスを使用するようにプリファレンスを変更する場合は、java.net.preferIPv6Addressesプロパティをtrueに設定します。これにより、アプリケーションがIPv6サービスに接続すると予測される環境でアプリケーションのテストとデプロイを行うことができます。

注意:
データベースを初期化する際にJavaが有効な場合、IPv6のサポートに必要な新しいシステム・クラスがすべてロードされます。そのため、ソフトウェアのコードに含まれるアドレスがアプリケーションに存在しない場合、IPv6の機能を使用するようにコードを変更する必要はありません。

複数のJDKのサポート

Oracle Database 12cリリース1 (12.1)から、Oracle JVMでは、最新のJDKバージョンを含む複数のJDKバージョンをサポートしています。通常、サポートされるバージョンは、デフォルト・バージョンとその次の上位バージョンです。Oracle Database 12cリリース1 (12.1)ではJDK 6およびJDK 7がサポートされており、JDK 6がデフォルトのJDKバージョンです。したがって、JDKバージョンを明示的に設定しない場合、有効なJDKバージョンはJDK 6となります。

ある時点でデータベースに有効なJDKバージョンは、1つのみです。ニーズに応じて、別のJDKバージョンに切り替えることができます。

注意:

- サポートされているJDKバージョンはいずれも1つずつのJDBCバージョンをサポートしています。

- CDBのJDKバージョンを変更すると、その内容がすべての対応するPDBが一律に影響を受けます。CDBに割り当てられたすべてのPDBは、同一のOracle JVMライブラリを共有するためです。したがって、同じCDBではPDB間で異なるバージョンのJDKを使用できません。たとえば、2つのPDB、pdb1およびpdb2をCDBで使用し、デフォルトのJDKバージョンが2つともJDK 6である場合、JDKバージョンをpdb1およびpdb2に対して同時にJDK 7に変更できます。pdb1でJDK 6を使用し、pdb2でJDK 7を使用することはできません。

- クラス・ファイルの検証に失敗する場合、複数の種類のエラーが存在する可能性があります。これらのエラーの一部(UnsupportedClassVersionErrorなど)は、データベースに永続的に残ります。したがって、(JDKの切替え後に)クラスが新しいJDKでの検証に合格しても、引き続きこれらのエラーはスローされます。これを解決するには、次のいずれかのオプションを使用して、クラスをデータベースに再ロードする必要があります。

- loadjavaの-forceオプションを使用する

- クラスを一度削除してから再びロードする

JDKバージョンの設定

この項では、次の2つのシナリオにおいてデータベースのJDKバージョンを設定する手順を説明します。

- 既存のデータベースを使用しない

- 既存のデータベースを使用する

既存のデータベースを使用しない

ORACLE_HOMEを使用してシステムにOracle Database 12cリリース1 (12.1)サーバーをインストールしたが、データベースをまだ作成していない場合は、特定のJDKバージョンでデータベースを作成できます。

JDK 6でデータベースを作成する場合は、これがデフォルトのJDKバージョンであるため、通常のデータベース作成手順を実行できます。JDK 7でデータベースを作成する場合は、次の手順を実行します。

1. 次のPerlスクリプトを実行します。

perl $ORACLE_HOME/javavm/install/update_javavm_binaries.pl 7

2. オプションで、プラットフォームに基づいてOracleを再リンクします。
Windowsプラットフォームの場合、再リンクは必要ありません。Windows以外のプラットフォームの場合、次のコマンドを使用してOracleを再リンクします。

cd $ORACLE_HOME/rdbms/lib
make -f ins_rdbms.mk ioracle

ins_rdbms.mkはMakeファイルの名前であり、ioracleはターゲットです。

3. 通常のデータベース作成手順を実行します。

注意:
後からこのORACLE_HOMEを使用して作成したデータベースのJDKバージョンは、JDK 7に設定されます。このようなデータベースのJDKバージョンを変更するには、「既存のデータベースを使用する」に示されている手順を実行します。

既存のデータベースを使用する

ORACLE_HOMEを使用してシステムにOracle Database 12cリリース1 (12.1)サーバーをインストールし、JDKバージョンxでデータベースを作成した場合、次の手順に従ってJDKバージョンをyに変更します。

1. ORACLE_HOMEを使用して実行されているすべてのデータベースを停止します。

注意:
Windowsプラットフォームの場合、特定のORACLE_SIDに対応するOracleサービスもすべて停止する必要があります。

2. 次のPerlスクリプトを実行します。

perl $ORACLE_HOME/javavm/install/update_javavm_binaries.pl y

3. オプションで、プラットフォームに基づいてOracleを再リンクします。
Windowsプラットフォームの場合、再リンクは必要ありません。Windows以外のプラットフォームの場合、次のコマンドを使用してOracleを再リンクします。

cd $ORACLE_HOME/rdbms/lib
make -f ins_rdbms.mk ioracle

ins_rdbms.mkはMakeファイルの名前であり、ioracleはターゲットです。

4. JDK yで使用するデータベースを起動します。

注意:
Windowsプラットフォームの場合、データベースを起動する前に、特定のORACLE_SIDに対応するOracleサービスもすべて起動する必要があります。

5. 非CDB脚注 2 の場合、これらの各データベース内で、SYSとして次の.sqlスクリプトを実行します。

$ORACLE_HOME/javavm/install/update_javavm_db.sql

注意:
Oracle RACの場合、次の手順を実行する必要があります。

- Perlスクリプト$ORACLE_HOME/javavm/install/update_javavm_binaries.plを実行し、それぞれのノードで、(適宜、プラットフォームに基づいて) Oracleをリンクします。

- 各データベース内で、手順5を1回繰り返します。

CDB脚注 3 の場合、次の手順を実行します。

1. 次のコマンドをSYSユーザーとして実行し、すべてのコンテナを開きます。

alter pluggable database all open;

2. シェルで次のコマンドを使用して、すべてのコンテナで$ORACLE_HOME/javavm/install/update_javavm_db.sqlスクリプトを実行します。

perl -I $ORACLE_HOME/rdbms/admin $ORACLE_HOME/rdbms/admin/catcon.pl -b
<some_log_file_name> $ORACLE_HOME/javavm/install/update_javavm_db.sql

注意:
前述のPERLコマンドを実行する前に、PATH変数に値$ORACLE_HOME/binが含まれていることを確認します。このようにPATHを設定して、catcon.plスクリプトを実行したときSQL*Plusが見つかるようにする必要があります。

関連項目:
CDBおよび非CDBの詳細は、『Oracle Database管理者ガイド』

専用モード・セッションのメモリー・モデル

Oracle Database 10g以降のOracle JVMには、専用サーバーを介してデータベースに接続するセッション用に新しいメモリー・モデルが用意されています。Oracleに関連する基本的なメモリー構造を次に示します。

- システム・グローバル領域(SGA)
SGAは、SGAコンポーネントと呼ばれる共有メモリー構造のグループで、1つのOracle Databaseインスタンスのデータと制御情報が含まれます。SGAは、すべてのサーバー・プロセスとバックグラウンド・プロセスで共有されます。SGAに格納されるデータには、キャッシュ・データ・ブロックや共有SQL領域などがあります。

- プログラム・グローバル領域(PGA)
PGAは、サーバー・プロセスのデータおよび制御情報が含まれるメモリー領域です。これは、サーバー・プロセスの起動時にOracleで作成される非共有メモリーです。PGAへのアクセスは、サーバー・プロセスごとに排他的です。各サーバー・プロセスごとに1つのPGAが存在します。バックグラウンド・プロセスにも独自のPGAが割り当てられます。1つのOracleインスタンスに付随するすべてのバックグラウンド・プロセスおよびサーバー・プロセスに割り当てられるPGAメモリーの合計は、PGA総計と呼ばれます。

メモリーを管理するには、データベースによって自動的に管理およびチューニングする方法が最も簡単です。これを実行するには、ほとんどのプラットフォームの場合、ターゲット・メモリー・サイズ初期化パラメータ(MEMORY_TARGET)と最大メモリー・サイズ初期化パラメータ(MEMORY_MAX_TARGET)のみを設定します。データベースでターゲット・メモリー・サイズにチューニングされ、必要に応じてSGAとPGA総計との間でメモリーが再分配されます。ターゲット・メモリー初期化パラメータは動的であるため、データベースを再起動せずにいつでもターゲット・メモリー・サイズを変更できます。ユーザーがターゲット・メモリー・サイズの設定を誤って高くしすぎないように、最大メモリー・サイズが上限として機能します。また、一部のSGAコンポーネントは簡単に縮小できないか、または最小サイズに抑える必要があるため、データベースではユーザーがターゲット・メモリー・サイズの設定を低くしすぎないようにします。

関連項目:
『Oracle Database管理者ガイド』

脚注の凡例

脚注1: いずれかのシステム・クラスと同じ名前を持つクラスを常に定義できるわけではありません。java.langなどのクラスが一部のパッケージに存在する場合、このような定義はコードによって明示的に妨げられます。
脚注 2: マルチテナント・コンテナ・データベース(CDB)ではないOracle Database。
脚注 3: 最低1つのPDBを含むOracle Databaseインストール。

2 Oracle DatabaseでのJavaアプリケーション

Oracle Databaseでは、標準のJavaアプリケーションが実行されます。ただし、Javaを統合したOracle Database環境は、一般的なJava開発環境とは異なります。この章では、Oracle DatabaseでのJavaアプリケーションの作成、インストールおよびデプロイについて、一般的なJava開発環境との基本的な相違について説明します。この章の内容は、次のとおりです。

- Javaアプリケーションにインポーズされるデータベース・セッション

- Javaアプリケーションの実行制御

- Javaのコード、バイナリおよびリソースの格納

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

- サーバー上のユーザー・インタフェース

- クラスの短縮名

- Oracle DatabaseのClass.forName()

- オペレーティング・システム・リソースの管理

- Oracle DatabaseでのRuntime.exec機能の使用

- JMXを使用したアプリケーションの管理

- Oracle Databaseのスレッド

- 共有サーバーに関する考慮事項

Javaアプリケーションにインポーズされるデータベース・セッション

Javaを統合したOracle Databaseでは、Javaアプリケーションはデータベース・セッションのコンテキスト内に存在します。Oracle JVMセッションは、従来のOracleセッションとまったく同様です。Oracle JVMの各セッションは、セッション内の複数のコールにわたって、クライアントがアクセスするJavaアプリケーションの状態を保持します。

図2-1に、各Javaクライアントが、データベース内のJavaアプリケーションを実行する環境としてデータベース・セッションを起動する方法を示します。Javaの各データベース・セッションには、独立したガベージ・コレクタ、セッション・メモリーおよびコール・メモリーがあります。

図2-1 各データベース・セッション内のJava環境

セッションのコンテキストで、クライアントは次の内容を実行します。

1. データベースに接続してセッションをオープンします。

2. データベース内でJavaを実行します。これはコールとも呼ばれます。

3. 必要に応じてコールを実行し、セッション内で処理を続行します。

4. セッションを終了します。

1つのセッション内で、クライアントには独自のJava環境があります。クライアントには、セッションごとに個別のJVMが個々に起動されるように見えますが、実際の実装はそれよりも効率的です。セッション内では、Oracle JVMがアプリケーションのスケーラビリティを管理します。ある単一のクライアントからのすべてのコールは、そのクライアントのセッションで管理され、各クライアントからのコールは個別に処理されます。Oracle JVMは、クライアント間の読取り専用データの共有を最大にし、セッションごとの増分フットプリントを最小限にすることで、 複数のクライアントのパフォーマンスを最大にします。

基盤となるサーバー環境では、セッション、ネットワーク、状態および他の共有リソース管理の問題に関する詳細が、Javaコードに対して明示されません。staticとして定義されたフィールドは、クライアントに対してローカルです。メモリーはセッションの境界を超えて使用できないため、クライアントは他のクライアントのstaticフィールドにはアクセスできません。各クライアントは、それぞれのセッション内でJavaアプリケーション・コールを実行するため、各クライアントのアクティビティは他のクライアントとは切り離されています。コール中にオブジェクトを異なるクラスのstaticフィールドに格納し、それを次のコールで使用できます。Javaプログラムの状態はすべてプライベートで、セッション全体にわたって存続します。

Oracle JVMは、セッション内で次の内容を管理します。

- Javaのstaticフィールドが参照するすべてのオブジェクト、これらのオブジェクトが参照するすべてのオブジェクトなど(オブジェクトの推移閉包まで)

- セッションを作成したクライアントのガベージ・コレクション

- staticフィールドのセッション・メモリーおよびコール間での必要なメモリー

- 1つのコール内に存在するフィールドのコール・メモリー

Javaアプリケーションの実行制御

Java 2 Platform, Standard Edition (J2SE)環境では、クラスの実行時にインタプリタからコールされるmain()メソッドを使用してJavaアプリケーションを開発します。main()メソッドは、コマンドラインで次のコマンドを入力したときにコールされます。

java classname

このコマンドは、Javaインタプリタを起動し、実行対象のクラス(つまり、classnameで指定されたクラス)をJavaインタプリタに渡します。インタプリタがmain()をコールすることで、クラスがロードされ、アプリケーションの実行が開始されます。ただし、main()メソッドをコールしても、データベース内のJavaアプリケーションは起動されません。

データベース内のJavaアプリケーションをロードした後は、ロードされたクラス内の任意のstaticメソッドをコールすることでJavaコードを実行できます。実行するには、クラスやメソッドが公開されている必要があります。Oracle Databaseの場合、main()はJavaアプリケーションのエントリ・ポイントとはみなされません。Javaアプリケーションを実行するときは、ロードされたクラス内のメソッド名をエントリ・ポイントとして指定します。

たとえば、標準のJava環境では、次のコマンドを実行することでサーバーのJavaオブジェクトを起動します。

java myprogram

myprogramには、main()メソッドが組み込まれているクラスの名前を指定します。myprogramでは、main()がただちにmymethod()をコールして、着信情報を処理します。

Oracle Databaseでは、データベースにmyprogram.classファイルをロードし、エントリ・ポイントとしてmymethod()を公開します。これで、クライアントまたはトリガーによって、明示的にmymethod()が起動されます。

Javaのコード、バイナリおよびリソースの格納

標準的なJava開発環境では、Javaのソース・コード、バイナリおよびリソースは、次のようにファイルとしてファイルシステムに格納されます。

- ソース・コード・ファイルは、.javaファイルとして保存されます。

- コンパイルされたJavaバイナリ・ファイルは、.classファイルとして保存されます。

- リソースは、.propertiesファイルや.serファイルなどの任意のデータファイルでファイルシステム階層に格納され、実行時にロードまたは使用されます。

また、Javaアプリケーションを実行する場合は、CLASSPATHを設定し、.classファイルが格納されているファイルシステムのファイルまたはディレクトリ・パスを指定します。Javaでは、これらのファイルをZIPファイルやJavaアーカイブ(JAR)ファイルなどの単一のアーカイブ形式にまとめることもできます。

これらの概念は、いずれもOracle Database環境では異なります。

表2-1に、Oracle DatabaseによるJavaクラスの処理方法と依存クラスの位置の特定方法を示します。

表2-1 Javaのコードとクラスの説明

Javaのコードとクラス

説明

Javaのコード、バイナリおよびリソースの格納

Oracle Databaseの場合、ソース・コード、クラスおよびリソースはデータベース内に常駐するため、Javaスキーマ・オブジェクトと呼ばれ、これは1つのスキーマが1つのデータベース・ユーザーに対応しています。Javaスキーマ・オブジェクトには、ソース、クラスおよびリソースの3つのタイプがあります。.java、.class、.sqlj、.propertiesまたは.serファイルはサーバー上にありません。これらのファイルは、適切なJavaスキーマ・オブジェクトにマップされます。

Javaクラスの位置の特定

Javaのソース、クラスおよびリソースのスキーマ・オブジェクトを検索するには、CLASSPATHのかわりに、リゾルバを使用して1つ以上のスキーマを指定します。

データベースにロードされるJavaクラス

コマンドライン・インタフェースを使用しない場合、Javaファイルをスキーマ・オブジェクトとしてデータベースにロードし、Oracle JVMでこれらを使用できるようにする必要があります。図2-2に示すように、loadjavaツールを使用して、ソース・ファイルを標準のクラス・ファイルにコンパイルする、Oracle JVMのJavaコンパイラをコールできます。

関連項目:
「コマンドライン・インタフェースの使用」

また、図2-2では、loadjavaツールを使用して、システム・データベース表に格納されているオプションの値を設定できることを示しています。これらのオプションは、特にJavaソース・ファイルの処理に影響を与えます。

図2-2 Oracle DatabaseへのJavaのロード

各Javaクラスは、スキーマ・オブジェクトとして格納されます。オブジェクトの名前は、含まれているパッケージの名前も含めたクラスの完全修飾名から導出されます。たとえば、Handleクラスのフルネームは、次のようになります。

oracle.aurora.rdbms.Handle

Javaスキーマ・オブジェクト名では、ピリオドがスラッシュで置換されるため、前述のクラスのフルネームは、次のようになります。

oracle/aurora/rdbms/Handle

Oracle Databaseでは、最大4000文字までのJava名を使用できます。ただし、Javaスキーマ・オブジェクトには30文字を超える名前は指定できません。したがって、スキーマ・オブジェクト名に30文字を超える名前が指定された場合は、スキーマ・オブジェクトの短縮名または別名が生成されます。それ以外の場合は、完全修飾名(フルネームとも呼ばれる)が使用されます。フルネームは、必要に応じて任意のコンテキストで指定できます。必要な場合は、名前のマッピングがOracle Databaseによって処理されます。

関連項目:
「クラスの短縮名」および「システム・クラス」

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

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

1. Javaソース・コードをいつコンパイルするかを決定します。

2. データベース内のJavaクラスの位置の特定に、デフォルトのリゾルバを使用するか、別のリゾルバを使用するかを決定します。

3. クラスをデータベースにロードします。クラスにデフォルトのリゾルバを使用しない場合は、ロード・コマンドで別のリゾルバを指定してください。

4. クラスまたはメソッドを公開します。

この項の内容は、次のとおりです。

- Javaクラスのコンパイル

- クラス依存関係の解決

- クラスのロード

- 実行権限の付与

- 現行ユーザーの制御

- Javaアップロードのチェック

- 公開

- 監査

Javaクラスのコンパイル

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

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

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

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

注意:
loadjavaツールを使用してコンパイルを実行する場合は、コンパイラ・オプションを指定できます。詳細は、「コンパイラ・オプションの指定」を参照してください。

この項の内容は、次のとおりです。

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

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

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

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

- 自動再コンパイル

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

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

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

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

1. ソース・ファイルがソース・スキーマ・オブジェクトとしてロードされます。

2. ソース・ファイルがコンパイルされます。

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

4. コンパイル済のコードがクラス・スキーマ・オブジェクトに格納されます。

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

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

-resolveオプションを指定せずにデータベースにJavaソースをロードすると、実行時にクラスが必要になったときに、Oracle Databaseによってソースが自動的にコンパイルされます。ソース・ファイルは、ソース・スキーマ・オブジェクトにロードされます。

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

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

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

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

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

関連項目:
「データベース表に指定されるコンパイラ・オプション」

デフォルトのコンパイラ・オプション

コンパイル対象のソース・スキーマ・オブジェクトに、JAVA$OPTIONS表のエントリもコマンドラインのオプション値も指定されていない場合は、次のデフォルト値が使用されます。

- encoding=System.getProperty("file.encoding");

- online=true
このオプションは、SQLJ構文が含まれているJavaソースにのみ適用されます。

- debug=true
このオプションは、次のように指定した場合と同じです。

javac -g

コマンドラインのコンパイラ・オプション

loadjavaツールにencodingコンパイラ・オプションを指定すると、.javaファイルのエンコーディングが識別されます。このオプションは、JAVA$OPTIONS表内の一致する値をすべてオーバーライドします。この値は、次のように指定した場合と同じです。

javac -encoding

このオプションはソース・ファイルのロード時のみ有効です。

データベース表に指定されるコンパイラ・オプション

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-2に、これらのメソッドのパラメータを示します。

表2-2 nameパラメータとoptionパラメータの定義

パラメータ

説明

name

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

option

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

最初、スキーマにはJAVA$OPTIONS表はありません。JAVA$OPTIONS表を作成するには、DBMS_JAVAパッケージのjava.set_compiler_optionプロシージャを使用して値を設定します。このプロシージャは、表が存在しない場合に表を作成します。パラメータは一重引用符で囲みます。次に例を示します。

SQL> execute dbms_java.set_compiler_option('x.y', 'online', 'false');

表2-3は、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
: 定義済の名前に一致するパターンはありません。デフォルトは空文字列規則です。

自動再コンパイル

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ツールには、依存関係管理機能を利用しない場合に、コンパイルと解決を強制的に実行する機能もあります。

クラス依存関係の解決

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番目のパラメータにはこれらのクラス・スキーマ・オブジェクトを検索するスキーマを定義します。

存在しないクラスへの参照の許可

リゾルバ仕様には、存在しないクラスへの未解決の参照を可能にする特別なオプションを指定できます。製品では内部クラスがまったく使用されないこともあります。標準の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ツールによって、参照される未定義のクラス定義が作成され、ロードされます。

バイトコード検証機能

JVMの仕様では、定義したクラスをJVMで使用するには、その前に.classファイルを検証する必要があります。Oracle JVMでは、クラスの解決時に検証が実行されます。

表2-4に、リゾルバで検出される問題と、発行される該当の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への参照であるかのように使用している場合、リゾルバはAがBを拡張または実装しているかどうかを確認します。たとえば、次のメソッドについて考えてみます。シグネチャでは暗黙的にBのインスタンスを戻すことになっていますが、そのボディはAのインスタンスを戻します。

B myMethod(A a)
{
return a;
}

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

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

関連項目:
クラスの解決とデータベースでのクラスのロードの詳細は、第12章「スキーマ・オブジェクトおよびOracle JVMユーティリティ」を参照してください。

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', '' );

クラスのロード

この項では、loadjavaツールを使用してデータベースにクラスをロードする概要について説明します。loadjavaツールを使用すると、ファイルからスキーマ・オブジェクトを生成して別のスキーマにロードできます。次に例を示します。

loadjava -u HR -schema TEST MyClass.java
Password: password

注意:
コマンドライン・インタフェースを使用する場合、クラスをスキーマ・オブジェクトとしてデータベースにロードする必要はありません。次に例を示します。

C:\oraclehome\bin>loadjava -u HR MyClass.java
Password: password

コマンドライン・インタフェースの詳細は、「コマンドライン・インタフェースの使用」を参照してください。

関連項目:
第12章「スキーマ・オブジェクトおよびOracle JVMユーティリティ」

loadjavaツールは、SQLコマンド内から実行することもできます。ファイルからコンパイルおよびロードする従来のJVMとは異なり、Oracle JVMはデータベース・スキーマ・オブジェクトからコンパイルおよびロードします。

表2-5に、従来のJVMで使用されるファイルに対応するデータベース・スキーマ・オブジェクトを示します。

表2-5 Javaファイルの説明

Javaファイルの種類

説明

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

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

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

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

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

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

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

表2-6に、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ビューにアクセスして、クラスとリソースが正しくロードされたことを確認できます。

ユーザー・クラスロード・クラスのメタデータの共有

データベース常駐クラスをロードするための組込みメカニズムによってロードされたクラスはシステム・クラスロードと呼ばれ、その他の方法によってロードされたクラスはユーザー・クラスロードと呼ばれます。データベースにクラスをロードする場合、クラスの表現はメモリーで作成され、その一部はクラス・メタデータと呼ばれます。クラス・メタデータはクラスを使用するセッションと同じであり、場合によっては共有できます。以前は、システム・クラスロード・クラスの場合のみ共有できていました。Oracle Database 11gからは、システム管理者の判断により、ユーザー・クラスロード・クラスのクラス・メタデータも共有できます。

関連項目:
付録B「クラスパスの拡張機能およびユーザー・クラスロード・メタデータ」

同じクラスの二重定義

同じスキーマに同じ名前の2つのクラス・オブジェクトは指定できません。この規則によって、次の2つの制限を受けることになります。

注意:
例外は、データベース常駐JARの-prependjarnamesオプションを使用する場合です。このオプションを使用する場合、同じスキーマに同じ名前の2つのクラスを指定できます。データベース常駐JARの詳細は、「データベース常駐JAR」を参照してください。

- 特定の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をロードします。

関連項目:
「システム・クラス」

データベース権限とJVMパーミッションの指定

クラスをロードするには、次のSQLデータベース権限が必要です。

- スキーマにロードする場合はCREATE PROCEDUREおよびCREATE TABLE権限。

- 別のスキーマにロードする場合はCREATE ANY PROCEDUREおよびCREATE ANY TABLE権限。

- oracle.aurora.security.JServerPermission.loadLibraryInClass. classname。

関連項目:
「クラスをロードするためのパーミッション」

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オプションを使用することで、強制的にクラスを再ロードできます。

データベース常駐JAR

11gリリース1(11.1)以降では、データベースにJARの内容をロードする場合、JAR自体を表すデータベース・オブジェクトを作成するオプションが用意されています。この方法で、JARオブジェクトと、JARからロードされたクラス、リソースおよびソース・オブジェクトとの関連付けを保持できます。その結果、次のことが可能です。

- 標準的なJVMと同じ方法で、符号付きJARとJARネームスペースの分離を使用します。

- JARから導出したクラスを管理する一方で、それを1つの単位としてデータベースにロードします。これは、JARからロードされたクラスを個別に再定義しない場合に便利です。また、外部ファイルシステム上のJARの内容や存続に関係なく、クラスの削除時にJARからロードされたクラス・セット全体を削除できます。

JARをデータベースにロードするには、loadjavaツールの次のオプションを使用します。

- -jarsasdbobjects

- -prependjarnames

loadjavaツール・オプションの詳細は、「loadjavaツール」の項を参照してください。

実行権限の付与

すべてのクラスを自分のスキーマにロードし、自分のスキーマの外部のクラスを参照しない場合は、クラスを実行する権限がすでにあります。自分のオブジェクトが同じスキーマにロードされた他のオブジェクトをコールするために必要な権限を持っています。つまり、クラスAがクラスBを起動する能力です。クラスAにはクラスBをコールする権限が付与されている必要があります。

Javaアプリケーションを定義するクラスは、その所有者のSQLスキーマの下にある、Oracle Database内に格納されます。デフォルトでは、特定のユーザーのスキーマに常駐するクラスは、セキュリティ保護のために他のユーザーからは実行できません。次の方法で、自分のクラスの実行権限を他のユーザーに付与できます。

- loadjava -grantオプションを使用します。

関連項目:
「loadjavaツール」

- 次のコマンドを使用します。

SQL> grant execute on myclass to HR;

myclassは、基礎となるJavaクラスの名前です。

注意:
Oracle Database 11gリリース1 (11.1)以前では、ストアド・プロシージャの実行権限を付与する場合、ストアド・プロシージャと、そのストアド・プロシージャによって参照されるJavaクラスの両方の実行権限が付与されます。Oracle Database 11gリリース以降では、基礎となるJavaクラスの実行権限も付与する場合、そのクラスに対する実行権限を明示的に付与する必要があります。これは、セキュリティの向上を目的として実装されています。

図2-3は、クラスを実行するために必要な権限を示しています。

図2-3 クラスの実行権限

関連項目:
JVMセキュリティのパーミッションの詳細は、第9章「Oracle Database Javaアプリケーションのパフォーマンス」を参照してください。

現行ユーザーの制御

PL/SQLコードの実行中は、常に現行ユーザーが存在します。Javaコードの実行にも同じ概念が使用されます。まず、現行ユーザーは、Javaコードを起動するセッションを作成するユーザーです。Javaメソッドは、対応するラッパーによってSQLまたはPL/SQLからコールされます。Javaラッパーは、JavaメソッドをPL/SQLストアド・プロシージャまたはファンクションとしてSQLおよびPL/SQLに公開する特殊なPL/SQLエンティティです。このようなラッパーは、有効な現行ユーザーを変更できます。有効な現行ユーザーをラッパーの所有者に変更するラッパーは、定義者権限ラッパーと呼ばれます。ラッパーが有効な現行ユーザーを変更しない場合、有効なユーザーはそのまま変わりません。

Javaラッパーは、デフォルトで定義者権限ラッパーです。これをオーバーライドするには、AUTHID CURRENT_USERオプションを使用してラッパーを作成します。

関連項目:
AUTHID CURRENT_USERオプションの詳細は、「トップレベルのコール仕様の作成」を参照してください。

Javaコードの実行中は常に、Javaコール・スタックが保持されます。スタックには、現在実行中のメソッドに対応する最も内側のフレームを含め、入力したJavaメソッドに対応するフレームがあります。デフォルトでは、Javaメソッドは、スタックで、現行ユーザーを変更せずに、つまり定義者権限ではなく現在の有効な実行者権限で、実行されます。

Javaクラスは、loadjava -definerオプションを使用してデータベースにロードできます。定義者属性がマークされているクラスのメソッドは、定義者権限メソッドになります。このようなメソッドが入力されると、定義者フレームと呼ばれる特殊なフレームがJavaスタックに作成されます。このフレームは、有効な現行ユーザーをこのようなクラスの所有者(定義者)に切り替えます。新しいユーザーIDは、定義者フレームがスタックからなくなるまで、あるいはネストされた定義者フレームが入力されるまで、すべての内部フレームに対して有効です。

したがって、SQLまたはPL/SQLからそのラッパーによってコールされたJavaメソッドの実行中は常に、有効なユーザーは次のいずれかになります。

- Javaスタックの最内部の定義者フレーム

- 最上部JavaメソッドのPL/SQLラッパーの所有者(定義者権限の場合)またはラッパーをコールしたユーザー。

販売分析に定義者権限プロシージャを使用する企業を考えてみます。地区ごとの販売統計を取得するには、analyzeプロシージャによって各地区のsales表にアクセスする必要があります。そのためには、各地区サイトにプロシージャが存在している必要があります。これによりメンテナンス上の問題が発生します。問題を解決するために、この企業ではanalyzeプロシージャの実行者権限バージョンを本社にインストールしました。

図2-4に示すように、すべての地区サイトで同じプロシージャを使用して、各地区のsales表を問合せできます。

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

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

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

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

Javaアップロードのチェック

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

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

表2-7 主なUSER_OBJECT列

名前

説明

OBJECT_NAME

オブジェクトの名前。

OBJECT_TYPE

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

STATUS

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

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

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エントリを検索します。

公開

Oracle Databaseでは、データベースにロードされたJavaメソッドは、公開されるとクライアントおよびSQLからコールできるようになります。オブジェクト自体、または個々のメソッドを公開できます。SQLのデータ操作言語(DML)文またはPL/SQLで、直接あるいは間接的にトリガーでコールするJavaストアド・プロシージャを作成する場合は、クラスの個々のメソッドを公開する必要があります。コール仕様を使用してメソッドへのアクセス方法を指定します。Javaプログラムは多数のクラスの様々なメソッドで構成されます。ただし、コール仕様で通常公開されるstaticメソッドは少数です。

関連項目:
第6章「コール仕様を使用した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

関連項目:

- 『Oracle Databaseセキュリティ・ガイド』

- 『Oracle Database SQL言語リファレンス』

サーバー上のユーザー・インタフェース

Oracle Databaseでは、ユーザー・インタフェースの表示に関連するライブラリも含めて、コアなJavaクラス・ライブラリはすべてサーバー上にあります。しかし、ユーザー・インタフェースを作成または表示するために、コードをサーバー上で実行することは適切ではありません。Oracle JVM環境でアプリケーションを実行しているユーザーは、Oracle Databaseを実行しているサーバーの表示と入力のハードウェアとの対話や依存は不可能です。

ディスプレイ、キーボードまたはマウスをサポートしないプラットフォームへの互換性の問題に対処するために、Java 1.4ではヘッドレスAbstract Window Toolkit(AWT)サポートが採用されています。このヘッドレスAWT APIによって、publicランタイム例外クラスjava.awt.HeadlessExceptionが新たに導入されました。ネイティブな表示デバイスに依存しているAppletクラスのコンストラクタ、軽量でないすべてのコンポーネントおよびToolkitクラスやGraphicsEnvironmentクラスのメソッドの多くは、プラットフォームで表示がサポートされていない場合に、HeadlessExceptionをスローするように変更されました。Oracle Databaseでは、ユーザー・インタフェースはクライアント・アプリケーションのみでサポートされます。したがって、Oracle JVMはヘッドレス・プラットフォームであり、これらのメソッドをコールするとHeadlessExceptionがスローされます。

ヘッドレスAWTでは、基礎となるネイティブな表示デバイスまたは入力デバイスにはアクセスしないほとんどのAWT計算が許可されます。実際に、ヘッドレスAWTは非常に強力な機能であり、プログラマに対してフォント、イメージ、印刷、および色やICC操作へのアクセスを提供します。たとえば、Oracle JVMで実行中のアプリケーションは、サーバー上でイメージを物理的に表示しようとしないかぎり、そのイメージを解析、操作および出力できます。標準のJVM実装は、ヘッドレス・モードで(プロパティを-Djava.awt.headless=trueに指定して)起動し、Oracle JVMの場合と同様のヘッドレスAWT制限で実行できます。Oracle JVMは、ヘッドレスAWTに関してJava Compatibility Kit(JCK)に完全に準拠しています。

関連項目:
http://www.oracle.com/technetwork/articles/javase/headless-136834.html

Oracle JVMでは、サウンド・サポートと同様のアプローチを採用しています。Oracle JVMのアプリケーションは、サウンドの再生や記録の目的で、基盤となるサウンド・システムにアクセスできません。また、システム・サウンド・リソースは、リソースにアクセスしようとするメソッドのサウンドAPI仕様に一致する方法では使用できません。たとえば、基盤となるシステム・サウンド・リソースへのアクセスを試みるjavax.sound.midi.MidiSystemのメソッドでは、システムが使用できないことを示すチェック済の例外MidiUnavailableExceptionがスローされます。ただし、ヘッドレスAWTサポートと同様に、Oracle Databaseでは、ネイティブなサウンド・デバイスなしでサウンド・ファイルを操作できるAPIをサポートしています。また、Oracle JVMは、サウンドAPIを実装する際、JCKに完全に準拠します。

クラスの短縮名

Javaソース、クラスおよびリソースは、サーバーのそれぞれのスキーマ・オブジェクトに格納されます。スキーマ・オブジェクトの名前は、関連するパスやパッケージ情報を含む完全修飾名から導出されます。ドットはスラッシュに置換されます。

ただし、スキーマ・オブジェクト名は最大30文字で、すべての文字が有効であり、データベース・キャラクタ・セットの文字に変換可能であることが必要です。完全修飾名が30文字を超える場合、または無効な文字または変換できない文字が含まれている場合、Oracle Databaseは、完全修飾名を短縮名または別名に変換して、その名前をスキーマ・オブジェクト名として使用します。Oracle Databaseは、それらの名前とその変換方法を追跡します。完全修飾名が30文字以下で、無効な文字や変換できない文字が含まれていない場合は、完全修飾名がスキーマ・オブジェクト名として使用されます。

Javaクラスとメソッドの名前はSQL識別子の最大長よりも長くなることがあるため、Oracle Databaseでは、SQLアクセスのために内部的に短縮名を使用します。Oracle DatabaseのDBMS_JAVAパッケージには、短縮名に対応する元のJavaクラス名を取得するLONGNAME()ファンクションがあります。

FUNCTION longname (shortname VARCHAR2) RETURN VARCHAR2

このファンクションは、別名を使用して指定されたJavaスキーマ・オブジェクトの完全修飾名を戻します。次に、無効なクラスの完全修飾名を表示するために使用する文の例を示します。

SELECT dbms_java.longname (object_name) FROM user_objects WHERE object_type = 'JAVA CLASS' and status = 'INVALID';

また、DBMS_JAVAパッケージのSHORTNAME()ファンクションを使用して、データベースにフルネームを指定することもできます。このファンクションは、フルネームを入力として取得し、対応する短縮名を戻します。このファンクションは、USER_OBJECTSビューの問合せによって、クラスが正しくロードされたことを検証する際に役立ちます。

FUNCTION shortname (longname VARCHAR2) RETURN VARCHAR2

関連項目:
「システム・クラス」

Oracle DatabaseのClass.forName()

JLSでは、Class.forName()について次のように記述されています。

クラスの完全修飾名を指定すると、このメソッドはクラスを検索、ロードおよびリンクしようとします。正常に実行されると、このクラスのClassオブジェクトへの参照を戻します。正しく実行されなかった場合は、ClassNotFoundExceptionのインスタンスがスローされます。

クラスの参照は、参照側のクラスにかわって常にClassLoaderのインスタンスを介して実行されます。Java Development Kit(JDK)実装とOracle JVM実装の違いは、クラスの検索方法です。

- JDKは、ClassLoaderの1つのインスタンスを使用して、環境変数CLASSPATHに指定されている一連のディレクトリ・ツリー・ルートを検索します。

- Oracle JVMは、クラスの検索方法を指定する複数のリゾルバを定義します。各クラスにはリゾルバが対応付けられており、各クラスは異なるリゾルバを保持できます。Class.forName()をコールするメソッドを実行すると、現在実行中のクラス(this)のリゾルバを使用してクラスが検索されます。

関連項目:
「クラス依存関係の解決」

予定にないリゾルバを使用してクラスを検索しようとすると、間違った結果となります。たとえば、スキーマXのクラスXがスキーマYのクラスYに対して、クラスZを参照するように要求する場合は、クラスXのリゾルバを使用しようとするとエラーになります。参照を実行しているのはクラスYであるため、クラスZの検索にはクラスYに対応付けられたリゾルバが使用されます。つまり、クラスが別のスキーマに入っているときに、別のクラスの異なるリゾルバを指定すると(異なるスキーマにクラスが存在する場合はデフォルトでこの状態になります)、クラスを検索できない場合があります。

このようなリゾルバの問題は、次の方法で解決できます。

- Classオブジェクト自体を指定してクラス名の参照を回避します。

- Class.forName()メソッドに対してClassLoaderインスタンスを指定します。

- classForNameAndSchema()メソッドに対してクラスとそのクラスが常駐するスキーマを指定します。

- ClassForName.lookupClass()に対してスキーマとクラス名を指定します。

- スキーマ名とクラス名でオブジェクトをシリアライズします。

注意:
システム・クラスがClass.forName()を起動すると、予期しない動作が発生することがあります。目的のクラスがSYSまたはPUBLICに常駐している場合のみ、そのクラスが検索されます。クラスがSYSまたはPUBLICのいずれにも常駐していない場合は、そのクラスに対してPUBLICシノニムを宣言できます。

この項の内容は、次のとおりです。

- Class.forName()へのClassLoaderの指定

- classForNameAndSchema()へのクラス名とスキーマ名の指定

- lookupClass()へのクラス名とスキーマ名の指定

- シリアライズでのクラス名とスキーマ名の指定

- Class.forNameの例

Class.forName()へのClassLoaderの指定

Oracle Databaseは、スキーマ内でのクラスの検索にリゾルバを使用します。各クラスには指定のリゾルバが対応付けられており、各クラスには異なるリゾルバを対応付けることができます。したがって、クラスの検索は対応付けられたリゾルバの定義によって決まります。ClassLoaderインスタンスは、指定されたクラスに基づいて検索に使用するリゾルバを判断します。Class.forName()にClassLoaderインスタンスを指定すると、クラスは、そのクラスのリゾルバに定義されているスキーマ内で検索されます。このClass.forName()の改良型に対する構文は次のとおりです。

Class.forName (String name, boolean initialize, ClassLoader loader);

次の例は、現行のクラス・インスタンスまたはコール側のクラス・インスタンスのクラス・ローダーを指定する方法を示します。

例2-1 現行のクラスからのリゾルバの取得

Class.getClassLoader()メソッドを使用することで、任意のインスタンスのクラス・ローダーを取得できます。次の例は、インスタンスxで表されたクラスのクラス・ローダーを取得します。

Class c1 = Class.forName (x.whatClass(), true, x.getClass().getClassLoader());

例2-2 コール側クラスからのリゾルバの取得

oracle.aurora.vm.OracleRuntime.getCallerClass()メソッドを使用することで、実行中のメソッドをコールしたインスタンスのクラスを取得できます。クラスを取得した後は、戻されたクラスのClass.getClassLoader()メソッドをコールします。次の例では、workForCaller()メソッドをコールしたインスタンスのクラスを取得します。次に、そのクラス・ローダーを取得し、Class.forName()メソッドに渡します。結果として、クラスの検索に使用されたリゾルバがコール側クラスのリゾルバとなります。

void workForCaller()
{
ClassLoader c1=oracle.aurora.vm.OracleRuntime.getCallerClass().getClassLoader();
...
Class c=Class.forName(name, true, c1);
...
}

classForNameAndSchema()へのクラス名とスキーマ名の指定

検索するスキーマを特定できるリゾルバを指定することで、クラスを検索する位置の問題を解決できます。または、クラスがロードされているスキーマを指定できます。クラスのロード先スキーマが判明している場合は、Oracle Databaseが提供するDbmsJavaクラスにある、classForNameAndSchema()メソッドを使用できます。このメソッドには、クラス名とそのクラスが常駐するスキーマ名の両方を指定し、このメソッドによって、指定されたスキーマでのクラスの位置が特定されます。

例2-3 スキーマ名とクラス名の指定

次の例は、save()メソッドを使用してスキーマ名とクラス名を保存する方法を示しています。クラス名とスキーマ名が取得され、DbmsJava.classForNameAndSchemaメソッドを使用してそのクラスの位置が特定されます。

import oracle.aurora.rdbms.ClassHandle;
import oracle.aurora.rdbms.Schema;
import oracle.aurora.rdbms.DbmsJava;

void save (Class c1)
{
ClassHandle handle = ClassHandle.lookup(c1);
Schema schema = handle.schema();
writeName (schema.getName());
writeName (c1.getName());
}

Class restore()
{
String schemaName = readName();
String className = readName();
return DbmsJava.classForNameAndSchema (schemaName, className);
}

lookupClass()へのクラス名とスキーマ名の指定

スキーマ名とクラス名が入った1つのString値をoracle.aurora.util.ClassForName.lookupClass()メソッドに指定できます。このメソッドをコールすると、指定されたスキーマでそのクラスの位置が特定されます。文字列は次の形式で指定する必要があります。

"<schema>:<class>"

たとえば、HRスキーマでcom.package.myclassの位置を特定するには、次のコードを使用します。

oracle.aurora.util.ClassForName.lookupClass("HR:com.package.myclass");

注意:
スキーマ名には大文字を使用してください。この場合、スキーマ名は大/小文字が区別されます。

シリアライズでのクラス名とスキーマ名の指定

クラスのシリアライズを解除すると、処理の一部として、名前に基づいてクラスが検索されます。検索が正常に行われるためには、シリアライズされたオブジェクトにクラス名とスキーマ名の両方が含まれている必要があります。

Oracle Databaseでは、オブジェクトをシリアライズまたはシリアライズを解除する際に、次のクラスを使用できます。

- oracle.aurora.rdbms.DbmsObjectOutputStream
このクラスはjava.io.ObjectOutputStreamを拡張し、適切な場所にスキーマ名を追加します。

- oracle.aurora.rdbms.DbmsObjectInputStream
このクラスはjava.io.ObjectInputStreamを拡張し、DbmsObjectOutputStreamによって書き込まれたストリームを読み取ります。このクラスはあらゆる環境で使用できます。Oracle Databaseで使用した場合は、スキーマ名が読み取られ、クラスを検索する際に使用されます。クライアントで使用した場合、スキーマ名は無視されます。

Class.forNameの例

次に、クラスを参照するいくつかのメソッドの例を示します。

import oracle.aurora.vm.OracleRuntime;
import oracle.aurora.rdbms.Schema;
import oracle.aurora.rdbms.DbmsJava;

public class ForName
{
private Class from;

/* Supply an explicit class to the constructor */
public ForName(Class from)
{
this.from = from;
}

/* Use the class of the code containing the "new ForName()" */
public ForName()
{
from = OracleRuntime.getCallerClass();
}

/* lookup relative to Class supplied to constructor */
public Class lookupWithClassLoader(String name) throws ClassNotFoundException
{
/* A ClassLoader uses the resolver associated with the class*/
return Class.forName(name, true, from.getClassLoader());
}

/* In case the schema containing the class is known */
static Class lookupWithSchema(String name, String schema)
{
Schema s = Schema.lookup(schema);
return DbmsJava.classForNameAndSchema(name, s);
}
}

この例では、次のメソッドを使用してクラスを検索します。

- インスタンスのクラスのリゾルバを使用するには、lookupWithClassLoader()をコールします。このメソッドによって、from変数のClass.forName()メソッドにクラス・ローダーが指定されます。from変数に指定されたクラス・ローダーは、このクラスにデフォルト設定されます。

- 特定のクラスのリゾルバを使用するには、明示したクラス名の後にlookupWithClassLoader()を指定してForName()をコールします。ForName()メソッドによって、from変数が指定のクラスに設定されます。lookupWithClassLoader()メソッドは指定されたクラスのクラス・ローダーを使用します。

- コール側クラスのリゾルバを使用するには、最初に、パラメータを指定せずにForName()メソッドをコールします。これにより、from変数がコール側クラスに設定されます。次に、lookupWithClassLoader()メソッドをコールし、コール側クラスのリゾルバを使用してクラスを検索します。

- スキーマを指定してクラスを検索するには、lookupWithSchema()メソッドをコールします。このメソッドは、classForNameAndSchema()メソッドにクラス名とスキーマ名を渡します。

オペレーティング・システム・リソースの管理

オペレーティング・システムのリソースは、どのコンピュータでも制限されています。Javaは、プログラミング言語であると同時に、コンピューティング・プラットフォームの提供を目指しているため、プラットフォームに依存しないクラス、およびプラットフォーム固有のリソースにアクセスするためのフレームワークが用意されています。Javaのクラス・メソッドはJVMを介してオペレーティング・システム・リソースにアクセスします。Javaのこのモデルには潜在的な問題があり、これは、ガベージ・コレクタが管理するのはJavaオブジェクトで、そのJavaオブジェクトが保持するオペレーティング・システム・リソースではない場合に、プログラマが全リソースの管理をそのガベージ・コレクタに委任することに起因しています。

さらに、共有サーバーを使用している場合、Javaオブジェクト内に保持されているオペレーティング・システム・リソースは、1つのセッションの複数のコールにわたって保持されると無効になる可能性があります。

関連項目:
「複数のコールに影響を与えるオペレーティング・システム・リソース」

次の各項では、これらの問題について説明します。

- オペレーティング・システム・リソースの概要

- ガベージ・コレクションとオペレーティング・システム・リソース

オペレーティング・システム・リソースの概要

一般に、オペレーティング・システム・リソースには次のリソースが含まれています。

オペレーティング・システム・リソース

説明

メモリー

Oracle Databaseはメモリーを内部的に管理し、オブジェクトを作成するとメモリーを割り当て、オブジェクトが不要になると解放します。言語とクラス・ライブラリでは、メモリーの割当ておよび解放の直接的な手段はサポートされていません。
関連項目: 「メモリー領域管理」。

ファイルとソケット

Javaにはファイル・リソースまたはソケット・リソースを表すクラスが含まれています。これらのクラスのインスタンスは、ファイル・ハンドルなど、オペレーティング・システムのファイルまたはソケットの構成メンバーを保持します。

スレッド

Oracle JVMスレッドでは、データベースによる複数の同時実行セッションのサポートで提供される機能に対して追加のスケーラビリティは提供されません。ただし、Oracle JVMは、Javaスレッドの完全なAPIをサポートしています。
関連項目: 「Oracle Databaseのスレッド」。

オペレーティング・システム・リソースへのアクセス

デフォルトでは、Javaユーザーはオペレーティング・システムの大半のリソースに直接アクセスできません。システム管理者は、JVMセキュリティ制限を変更することで、オペレーティング・システムのリソースにアクセスするパーミッションをユーザーに付与できます。JVMセキュリティは、Java 2セキュリティに準拠したシステム・リソースで施行されます。

関連項目:
Java 2セキュリティ

オペレーティング・システム・リソースの存続期間

オペレーティング・システム・リソースへのアクセスには、標準のコアJavaクラスとメソッドを使用できます。リソースにアクセスした後、そのリソースがアクティブである期間は、リソースの種類によって異なります。メモリーはガベージ・コレクションされます。専用モードのサーバーを使用している場合、ファイル、スレッドおよびソケットは、複数コールにわたって存続します。共有サーバー・モードでは、ファイル、スレッドおよびソケットはコール終了時に終了します。

関連項目:
「複数のコールに影響を与えるオペレーティング・システム・リソース」。

ガベージ・コレクションとオペレーティング・システム・リソース

メモリーがJavaオブジェクト・メモリーとオペレーティング・システムの構成メンバーの2つの領域に分割されているとします。Javaオブジェクト・メモリー領域にはすべてのオブジェクトと変数が含まれています。オペレーティング・システムの構成メンバーには、オペレーティング・システムが要求に応じてオブジェクトに割り当てるリソースがあります。これらのリソースにはファイルやソケットなどが含まれます。

基本的なプログラミング規則では、Javaオブジェクトとオペレーティング・システム構成メンバーの両方のメモリーをクローズするように規定されています。Javaプログラマは、ガベージ・コレクタによってメモリーが解放されると誤解することがあります。ガベージ・コレクタは、未使用のJavaオブジェクト・メモリーを収集するために作成されました。ただし、オペレーティング・システムの構成メンバーはクローズされません。オペレーティング・システムの構成メンバーは、Javaオブジェクトをガベージ・コレクションする前にプログラムでクローズする必要があります。

たとえば、オブジェクトがファイルをオープンするたびに、オペレーティング・システムはそのファイルを作成してオブジェクトにファイル・ハンドルを割り当てます。ファイルがクローズされないと、オペレーティング・システムはコールの終了またはJVMの終了までファイル・ハンドルの構成メンバーを保持します。そのため、これらの構成メンバーが不足する可能性があります。各オペレーティング・システムのハンドルは無限ではありません。ハンドルの不足を回避するには、メソッドを終了する前にリソースをクローズします。ソケットに連結されたストリームについてもソケットをクローズする前にクローズします。

パフォーマンス上の理由から、ガベージ・コレクタは各オブジェクトにハンドルがあるかどうかを確認できません。したがって、ガベージ・コレクタはJavaオブジェクトおよび変数を収集しますが、ハンドルを解放するための適切なオペレーティング・システム・メソッドは発行しません。

例2-4に、オペレーティング・システムの構成メンバーのクローズ方法を示します。

例2-4 オペレーティング・システム・リソースのクローズ

public static void addFile(String[] newFile)
{
File inFile = new File(newFile);
FileReader in = new FileReader(inFile);
int i;

while ((i = in.read()) != -1)
out.write(i);

/*closing the file, which frees up the operating system file handle*/
in.close();
}

inFileをクローズしない場合、Fileオブジェクトは最終的にはガベージ・コレクションされます。Fileオブジェクトがガベージ・コレクションされても、ファイルがクローズされていないため、オペレーティング・システムでは、そのファイルが使用中と判断されます。

注意:
リソースをクローズするために、Javaファイナライザを使用することが必要な場合もあります。ただし、ファイナライザではタイムリな実行が保証されません。また、ガベージ・コレクタに時間的な余裕があると、ファイナライザは実行するためにキューに挿入されます。ファイナライザ内のリソースをクローズすると、JVMが終了するまでリソースが解放されない可能性があります。メソッドの中でリソースをクローズすることが最も確実な方法です。

Oracle DatabaseでのRuntime.exec機能の使用

Java仮想マシンは、Java Standard Editionのjava.lang.Runtime.execメソッドのファミリーを完全にサポートしています。これらのメソッドによって、ユーザーが指定したコマンドを実行するための新しいオペレーティング・システム(OS)プロセスが生成されます。サーバーでは、これらのメソッドを慎重に使用する必要があります。Java仮想マシンでは、OSコマンドの実行許可はデフォルトですべてのデータベース・ユーザーには付与されず、権限のある管理者のみがこれを発行します。DBAは、「Oracle DatabaseでのRuntime.exec機能のセキュアな使用」の項を参照して、推奨事項に従ってください。また、これらの許可をデータベース・ユーザーに発行する際には慎重に行う必要があります。

JMXを使用したアプリケーションの管理

この項の内容は、次のとおりです。

- JMXの概要

- セッションでのJMXの有効化と起動

- Oracle JVM JMXのデフォルト設定と構成可能性

- dbms_java.start_jmx_agentへのSQLコールの例

- JConsoleを使用したOracle JVMの監視および制御

- セキュリティに関する重要な注意点

- JMXの共有サーバーの制限事項

JMXの概要

JMX(Java Management Extensions)は、アプリケーション、システム・オブジェクト、デバイス、サービス指向のネットワーク、JVM(Java仮想マシン)を管理および監視するツールを提供するJavaテクノロジです。このAPIを使用すると、そのクラスの動的な作成と変更が可能です。そのため、リソースが作成、インストールおよび実装されると、このテクノロジを使用してリソースを監視および管理できます。また、JMX APIにはリモート・アクセスが含まれているため、リモート管理プログラムはこのような目的で実行中のアプリケーションと対話できます。

JMXでは、特定のリソースは、MBean(マネージドBean)と呼ばれる1つ以上のJavaオブジェクトで構成されます。これらのMBeanは、管理エージェントとして機能するコア・マネージド・オブジェクト・サーバー(MBeanサーバーと呼ばれる)に登録され、Javaプログラミング言語に対応するほとんどのデバイスで実行できます。JMXエージェントは、MBeanが登録されるMBeanサーバーと、MBeanを処理するサービスのセットで構成されます。

関連項目:

- http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html

- http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html

セッションでのJMXの有効化と起動

Javaを実行しているセッションでJMXサービスを有効化および実行するために、JMXSERVERロールおよびdbms_java.start_jmx_agentプロシージャが提供されています。JMXSERVERロールには、セッションでMBeanServerとJMXエージェントを起動および実行できる特定のJavaパーミッションが付与されます。プロシージャdbms_java.start_jmx_agentは、特定のセッションで、セッションの期間内は通常アクティブのままのエージェントを起動します。JMXを有効にして起動するには、次の操作を実行します。

1. SYSまたはSYSTEMからJMXSERVERを取得します。

SQL> grant jmxserver to HR;

HRはユーザー名です。

2. プロシージャdbms_java.start_jmx_agentを起動して、セッションでJMXを起動します。dbms_java.start_jmx_agentプロシージャは、次の引数を使用して起動できます。
port: JMXリスナーのポート。このパラメータの値は、Javaプロパティcom.sun.management.jmxremote.portを設定します。

ssl: Javaプロパティcom.sun.management.jmxremote.sslの値を設定します。値がtrueおよびfalseの場合は、無視されます。

auth: プロパティcom.sun.management.jmxremote.authenticateの値で、それ以外の場合は、Java Authentication and Authorization Service (JAAS)資格証明のセミコロンで区切られたリスト。値は大/小文字が区別されません。

各引数は、nullをデフォルト値としてnullにするか、または省略できます。引数がnullの場合、セッションの対応するプロパティの以前からある値は変更されません。

注意:
dbms_java.start_jmx_agentのパラメータに対応するJavaプロパティは、標準のJava 5.0 JMXドキュメントで指定されたJavaプロパティのセットからのものです。Java JMXプロパティの完全なリストは、http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.htmlを参照してください。

dbms_java.start_jmx_agentプロシージャは、OJVM JMXサーバーおよびリスナーをアクティブ化するエージェントを起動します。JMXサーバーは、現行セッションで1つ以上のデーモン・スレッドとして実行され、通常、セッションの期間内は使用可能です。JMXエージェントをセッションで起動すると、セッションで実行中のJavaコードを監視できます。

dbms_java.start_jmx_agentプロシージャは、Javaメソッドoracle.aurora.rdbms.JMXAgent.startOJVMAgentのPL/SQLラッパーで、これは、Javaストアド・プロシージャからプログラムでコールすることもできます。startOJVMAgentメソッドは、JMXサーバーとJMX接続デーモン・スレッドを起動してから終了します。専用サーバーでは、これらのスレッドはセッションの存続期間中はアクティブ状態を維持できますが、コールとコールの時間間隔は非活性状態になります。これらの時間間隔が短い場合、同じソケット接続が透過的に再開されます。これによって、JConsoleなどのクライアントは複数のコールにわたって接続を維持できます。

関連項目:
JMXの共有サーバーの制限事項

JMX監視の別のモードが、EXIT_CALL_WHEN_ALL_THREADS_TERMINATEポリシーで可能になります。コール終了ポリシーにOracleRuntime.EXIT_CALL_WHEN_ALL_THREADS_TERMINATEを設定すると、Javaコールがプログラムで終了されるまでstartOJVMAgentメソッドを起動するコールでJMXサーバーを引き続き実行するようにセッションを構成できます。このモードは、様々なJavaタスクが特定のMBeanの操作としてJMXクライアントから起動されている場合に便利です。このように、継続的なJMXの管理および監視がこれらの操作によって実行されます。jmxserv.Loadなど、このようなBeanのJVM JMXデモを参照してください。

Oracle JVM JMXのデフォルト設定と構成可能性

dbms_java.start_jmx_agentをアクティブにする場合、プロパティcom.sun.management.jmxremoteはtrueに設定されます。start_jmx_agentを起動する前に、JMXSERVER権限のユーザーは、次の方法で様々な管理プロパティを初期設定できます。

- PL/SQLファンクションdbms_java.set_propertyを使用します。

- メソッドjava.lang.System.setPropertyを起動します。

JMXSERVERロールのユーザーは、Javaプロパティcom.sun.management.config.fileで指定されたデータベース常駐Javaリソースのプロパティも初期設定できます。com.sun.management.config.fileが設定されていない場合、このリソースのデフォルト名はlib.management.management.propertiesです。このリソース・メカニズムは、標準のファイルベースのJMX構成管理のOracle JVM拡張機能です。これは、セキュリティの向上とスキーマごとの管理を提供するため、Oracle JVMにとって優れたメカニズムです。リソースがスキーマに存在しない場合、ファイルの読取りはフォールバックとして行われます。com.sun.management.config.fileが設定されていない場合、デフォルトのファイル・パスは$(java.home)/lib/management/management.propertiesです。Oracle Database 12cでは、このファイルに次の初期設定が含まれています。

com.sun.management.jmxremote.ssl.need.client.auth = true
com.sun.management.jmxremote.authenticate = false

プロパティcom.sun.management.jmxremote.ssl.need.client.authとcom.sun.management.jmxremote.sslを併用すると、クライアントおよびサーバー証明書を使用する、双方向暗号化SSL認証のJMXが設定されます。com.sun.management.jmxremote.sslのデフォルト値はtrueです。この構成はデフォルトであり、JAASパスワード認証よりも好まれます。

注意:
詳細は、次のWebサイトにアクセスしてください。

- http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html

- http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html

注意:
パスワードのファイルベース・ストアを提供するデフォルトのJMXログイン・モジュールは、セキュリティ上の理由からOracle JVMでサポートされていません。そのため、SSLクライアント認証のかわりにJAASパスワード認証を使用する必要がある場合、この項で示すように、一時的なJAAS資格証明をauthパラメータとしてdbms_java.start_jmx_agentに安全に渡すか、または安全なカスタムLDAPログイン・モジュールを使用するようにJMXを構成します。

dbms_java.start_jmx_agentへのSQLコールの例

JMXサーバーの起動例を次に示します。

- 前述の項で説明したようなデフォルトの設定、または同じセッションの以前に設定された値を使用してJMXサーバーおよびリスナーを起動します。

call dbms_java.start_jmx_agent();

- 前述の項で説明したようなデフォルトの設定、または同じセッションの以前に設定された値を使用してJMXサーバーおよびリスナーを起動します。

call dbms_java.start_jmx_agent(null, null, null);

- JMXサーバーおよびリスナーをポート9999で起動します。他のJMX設定は、デフォルト値または同じセッションで以前に設定された値です。

call dbms_java.start_jmx_agent('9999');

- JMXサーバーおよびリスナーをポート9999で起動します。他のJMX設定は、デフォルト値または同じセッションで以前に設定された値です。

call dbms_java.start_jmx_agent('9999', null, null);

- JMXサーバーおよびリスナーを起動します。JMX設定は、デフォルト値または同じセッションで以前に設定された値です。JAAS資格証明monitorRole/1z2xおよびcontrolRole/2p3oを使用します。

call dbms_java.start_jmx_agent(null, null, 'monitorRole/1z2x;controlRole/2p3o');

これらの資格証明は一時的なものです。プロパティcom.sun.management.jmxremote.authenticateはtrueに設定されています。

- JMXリスナーを、SSLやJAAS認証は使用せず、ポート9999で起動します。開発またはデモンストレーションの場合にのみ使用します。

関連項目:
「セキュリティに関する重要な注意点」

call dbms_java.start_jmx_agent('9999', 'false', 'false');

JConsoleを使用したOracle JVMの監視および制御

この項では、JConsole(標準のJMXクライアント・ツール)を使用して、Oracle JVMを監視および制御する方法について説明します。JConsoleは、標準のJava JDKの構成要素です。

この項の内容は、次のとおりです。

- jconsoleコマンド

- JConsoleインタフェース

- OracleRuntime MBean

- メモリーのしきい値

注意:
JConsoleを使用してデータベース内のJavaを監視するには、サーバー側のJavaセッションでJMXエージェントが実行されている必要があります。詳細は、「セッションでのJMXの有効化と起動」を参照してください。

jconsoleコマンド

JConsoleを起動するにはjconsoleコマンド構文を使用します。JConsoleツールを開始する最も簡単な書式は次のようになります。

jconsole [hostName:portNum]

各項目は次のとおりです。

- hostnameは、アプリケーションを実行しているシステムの名前です。

- portNumは、JMXリスナーのポート番号です。

次の例では、デフォルトのポート9999を使用してexample.comという名前のホストに接続します。このモードでは、認証や暗号化は行われません。このモードは、デモやテストの場合のみに適しており、このモードを使用して、次のコマンドで開始するOracle JVMのJMXセッションに接続できます。

call dbms_java.start_jmx_agent(portNum, false, false);

サーバーのデーモン・スレッドが実行中で休止していない場合にのみ、JConsoleからOracle JVMに接続し対話できます。つまり、指定されたポートでJMXサーバーを実行するセッションに、アクティブなJavaコールが存在する必要があります。後続のJavaコール間の時間間隔中にJMXサーバーはその状態と統計情報を保持しますが、JConsoleと通信できません。

関連項目:
セキュリティに関する重要な注意点

JConsoleインタフェース

JConsoleインタフェースは、次のタブで構成されています。

- 「Summary」タブ
Oracle JVMに関する概要情報と、JMXで監視される値が表示されます。詳細は、「Oracle JVMの概要情報の表示」を参照してください。

- 「Memory」タブ
メモリーの使用量に関する情報が表示されます。詳細は、「メモリー使用量の監視」を参照してください。

- 「Threads」タブ
スレッドの使用状況に関する情報が表示されます。詳細は、「スレッドの使用状況の監視」を参照してください。

- 「Classes」タブ
クラスのロードに関する情報が表示されます。詳細は、「クラスのロードの監視」を参照してください。

- 「MBeans」タブ
MBeanに関する情報が表示されます。詳細は、「MBeanの監視および管理」を参照してください。

- 「VM」タブ
Oracle JVMに関する情報が表示されます。詳細は、「VM情報の表示」を参照してください。

重要:
Oracle Database 12cリリース1 (12.1)では、収集されてJConsoleに渡されるデータは、JMXエージェントを実行するOracle JVMセッションに限定されます。このデータには、Oracle JVMで実行している他のセッションの属性は含まれません。OracleRuntime MBeanは例外で、WholeJVM_ AttributesおよびOracle JVMの操作についての情報を多数提供します。OracleRuntime MBeanの詳細は、「OracleRuntime MBean」を参照してください。

Oracle JVMの概要情報の表示

JConsoleインタフェースの「Summary」タブを使用して、Oracle JVMの概要情報を表示できます。このタブには、スレッドの使用状況、メモリー使用量、クラスのロード、VMやオペレーティング・システムのその他の仕様に関する主な監視情報が表示されます。

JMXエージェントを実行するOracle JVMセッションとJConsoleとの接続が成功すると、次の図のような「Overview」タブが表示されます。

図2-6 JConsoleインタフェースの「Overview」タブ

表2-10で、「Overview」タブに表示されるフィールドについて説明します。

表2-10 JConsoleインタフェースの「Overview」タブのフィールドの説明

フィールド

説明

稼働時間

Oracle JVMセッションの実行時間。

プロセスCPU時間

Oracle Database 12cリリース1 (12.1)では、Oracle JVMセッションに関するこの情報は収集されません。

ライブ・スレッド

有効なデーモン・スレッドと非デーモン・スレッドの現在の数。

ピーク

Oracle JVMの起動以降の有効なスレッドの最大数。

デーモン・スレッド

有効なデーモン・スレッドの現在の数。

開始合計

Oracle JVMを起動してから開始したスレッドの合計数。デーモン・スレッド、非デーモン・スレッド、終了したスレッドが含まれます。

現在のヒープ・サイズ

現在ヒープで占められているKB数。

コミット済メモリー

ヒープで使用するために割り当てられるメモリーの合計。

最大ヒープ・サイズ

ヒープで占められる最大KB数。

ファイナライズを保留中のオブジェクト

最終段階に向けて保留中のオブジェクトの数。

ガベージ・コレクタ情報

ガベージ・コレクタに関する情報。名前、実行したコレクションの数、ガベージ・コレクションの実行に費やす合計時間などです。

現在ロードされているクラス

実行するために、現在メモリーにロードされているクラスの数。

ロードされているクラスの合計

セッションを開始してから、セッション・メモリーにロードされたクラスの合計数。

アンロードされているクラスの合計

メモリーからアンロードされたクラスの数。Oracle Database 12cリリース1 (12.1)の場合、通常はゼロになります。

合計物理メモリー

Oracle Database 12cリリース1 (12.1)では、Oracle JVMセッションに関するこの情報は収集されません。そのため、表示される値はゼロになります。

空き物理メモリー

Oracle Database 12cリリース1 (12.1)では、Oracle JVMセッションに関するこの情報は収集されません。そのため、表示される値はゼロになります。

コミット済仮想メモリー

Oracle Database 12cリリース1 (12.1)では、Oracle JVMセッションに関するこの情報は収集されません。そのため、表示される値はゼロになります。

メモリー使用量の監視

JConsoleインタフェースの「Memory」タブを使用して、メモリー使用量を監視できます。このタブには、メモリー使用量とメモリー・プールに関する情報が表示されます。

図2-7に「Memory」タブを示します。

図2-7 JConsoleインタフェースの「Memory」タブ

「Memory」タブのグラフには、メモリー領域全体だけでなく特定のメモリー・プールに関するOracle JVMのメモリー使用量と時間が示されます。Oracle JVMに使用可能なメモリー・プールは、Oracle JVMの内部組織を反映し、Oracle JVMのメモリー・マネージャのオブジェクト・メモリーに対応しています。このリリースのOracle Databaseで使用可能なメモリー・プールは次のとおりです。

- New Generation領域
大部分のオブジェクトに対してメモリーが最初に割り当てられるメモリー・プールです。Eden領域とも呼ばれます。

- Old Generation領域
このメモリー・プールには、Eden領域にガベージ・コレクション・プロセスが残ったオブジェクトが含まれます。Survival領域とも呼ばれます。

- Malloc/Free領域
このメモリー・プールには、メモリーがmallocで割り当てられ、freeで解放されるオブジェクトが含まれます。

- End of Migration領域
このメモリー・プールには、セッション終了時の移行を残すオブジェクトが含まれます。

- Dedicated Session領域
このメモリー・プールは、Oracle Dedicated Sessionsモードでセッション・オブジェクトにメモリーを割り当てる場合に使用します。

- Paged Session領域
このメモリー・プールは、大きなサイズのセッション・オブジェクトが呼び出される場合、そのオブジェクトへのメモリーの割当てに使用します。

- Run領域
このメモリー・プールは、一時オブジェクトおよび補助オブジェクトにメモリーを割り当てる場合に使用します。

- Stack領域
このメモリー・プールは、スタックに似た方式でメモリーの割当てと解放が行われる一時オブジェクトにメモリーを割り当てる場合に使用します。

「Memory」タブの「Details」領域には、次の内容で現在のメモリーのマトリクスが表示されます。

- 使用済
セッションを実行するプロセスで現在使用されているメモリー量を示します。

- コミット済
メモリーがすでに割り当てられているかのように、Oracle JVMでの使用が保証されたメモリー量を示します。コミットされるメモリーの量は、時間の経過とともに変わります。ただし、コミットされるメモリーは、必ず使用済メモリー以上になります。

- 最大
メモリーの管理に使用できる最大メモリー量を示します。通常は、Oracle JVMの初期構成に対応しています。

「Memory」タブの右下隅にある棒グラフは、各メモリー・プールで消費されたメモリーを示します。使用済のメモリーがメモリー使用量のしきい値を超えると、棒グラフは赤に変わります。メモリー使用量のしきい値は、MemoryMXBeanの属性を使用して設定できます。詳細は、「メモリーのしきい値」を参照してください。

スレッドの使用状況の監視

JConsoleインタフェースの「Threads」タブを使用して、スレッドの使用状況を監視できます。

図2-8 JConsoleインタフェースの「Threads」タブ

「Threads」タブのグラフには、有効なスレッドの数と時間が表示されます。特定のタイプのスレッドが特定の色で示されています。

- マゼンタは、スレッドの合計数を表します。

- 赤は、スレッドの最大数を表します。

- 青は、有効なスレッドの数を表します。

このタブのスレッドのリストには、有効なスレッドが表示されます。リストのスレッドを選択すると、そのスレッドに関する情報が右側のペインに表示されます。スレッドの名前、状態、スタック・トレースなどの情報があります。

「Filter」フィールドは、スレッドの絞込みに役立ちます。

クラスのロードの監視

JConsoleインタフェースの「Classes」タブを使用して、クラスのロードを監視できます。このタブのグラフには、ロードされたクラスの数と時間が描画されます。

図2-9 JConsoleインタフェースの「Classes」タブ

MBeanの監視および管理

「MBeans」タブを使用して、MBeanを監視および管理できます。このタブには、プラットフォームMBeanサーバーに登録されたすべてのMBeanに関する情報が表示されます。

「MBeans」タブの左ペインのツリーはMBeanツリーと呼ばれ、オブジェクト名に従って体系化されたすべてのMBeanが表示されます。MBeanツリーでMBeanを選択すると、その属性、操作、通知、その他の情報が右側のペインに表示されます。たとえば、図2-10では、左側のMBeanツリーで「Old Generation」MemoryPool MBeanを選択しており、「Old Generation」MemoryPool MBeanの属性が右側に表示されています。

図2-10 MBeanの属性の表示

属性の値は、書込み可能な場合は設定できます。書込み可能な値は青で表示されています。たとえば、図2-10では、属性CollectionUaageThresholdおよびUsageThresholdが書込み可能です。

属性の値をダブルクリックすると、属性の値と時間を示すグラフも表示されます。たとえば、「GCManager」MBeanの「CollectionTime」プロパティの値をクリックすると、図2-11のようなグラフが表示されます。

図2-11 属性の値のグラフの表示

属性をクリックすると、複雑な属性の詳細を表示できます。たとえば、図2-12に示すように、メモリー・プールの属性「Usage」および「PeakUsage」の詳細を表示できます。

図2-12 「MBeans」タブの複雑な属性の詳細の表示

MBeanの「Operations」タブには管理機能のインタフェースがあります。たとえば、「Perform Garbage Collection」をクリックすると、メモリー・プールまたはメモリー・マネージャに対してガベージ・コレクションを開始できます。Oracle JVMのJMXデモ(javavm/demo/jmx/)には、Oracle JVMにロードされる追加のカスタムMBeanが複数用意されています。次の例で、「DBProps」MbeanのgetProp操作の結果を示します。

図2-13 JConsoleインタフェースの「MBeans」タブの「Operations」タブ

VM情報の表示

JConsoleインタフェースの「VM」タブを使用して、VM情報を表示できます。

図2-14 JConsoleインタフェースの「VM」タブ

OracleRuntime MBean

Oracle Database 11gリリース2(11.2)以降では、dbms_java.start_jmx_agentプロシージャをコールすると、新規のMBean(OracleRuntime)がOracle JVMプラットフォームMBeanのリストに追加されます。このMBeanはOracle JVMに固有のものです。

OracleRuntime MBeanの「Attributes」タブには、oracle.aurora.vm.OracleRuntimeクラスによって操作されるほとんどのパラメータが公開されます。図2-15に、OracleRuntime MBeanの「Attributes」タブを示します。

図2-15 OracleRuntime MBeanの「Attributes」タブ

黒で表示されるパラメータは読取り専用のため、変更できません。たとえば、JavaPoolSize、Platformなどです。青の値は読取り/書込みで、値が変更できることを表します。OracleRuntime MBeanのほとんどの属性は、現在のセッションに対してローカルです。

OracleRuntime MBeanのWholeJVM_属性はグローバルです。これらの属性は、パフォーマンス・ビューv$sessionおよびv$sesstatからの収集に従って、データベース・インスタンス内のすべてのJava対応セッションにおけるOracle JVMのメモリー使用量統計の合計を反映します。図2-16に、OracleRuntime MBeanのWholeJVM_属性を示します。

図2-16 OracleRuntime MBean

OracleRuntime MBeanの「Operations」タブには、oracle.aurora.vm.OracleRuntimeクラスの操作の多くが公開されます。

さらに、図2-17と図2-18に示すように、sessionsRunningJava操作およびsessionDetailsBySID操作を使用して、Javaが有効な特定のデータベース・セッションの各メモリー使用量の統計を監視できます。

図2-17 sessionsRunningJava操作

図2-18 sessionDetailsBySID操作

メモリーのしきい値

使用量のしきい値は、メモリー・プールの管理可能な属性です。コレクション使用量のしきい値は、ガベージ・コレクションされた一部のメモリー・プールの管理可能な属性です。プールの対応するしきい値のチェックを有効にするには、各属性を正の値に設定します。しきい値をゼロに設定すると、メモリー・プールのしきい値のチェックが無効になります。デフォルトでは、Oracle JVMのすべてのプールのしきい値のチェックは無効になっています。

使用量のしきい値とコレクション使用量のしきい値は、「MBeans」タブで設定されます。たとえば、左ペインのツリーからメモリー・プール「Old Generation」を選択し、このメモリー・プールの使用量のしきい値を20MBに設定して、コレクションのしきい値を1MBに設定した場合、しばらくすると、図2-19に示すように、しきい値交差イベントの数がカウントに表示されます。

図2-19 「MBeans」タブの使用量のしきい値とコレクション使用量のしきい値の設定

メモリー・プール「Old Generation」のメモリー使用量が20MBを超えると、JConsoleインタフェースのメモリー・プール「Old Generation」を表すグラフの一部が赤に変わります。赤い部分は、使用済メモリーの一部が使用量のしきい値を超えたことを示します。図2-20に示すように、ヒープ・メモリーを表すグラフも赤に変わります。

図2-20 使用済メモリーが使用量のしきい値を超えた場合のJConsoleインタフェースの「Memory」タブ

セキュリティに関する重要な注意点

SSLと認証を無効にしてリモート・リスナーを起動すると、一般的なセキュリティのガイドラインに違反するため、攻撃に対してサーバーが脆弱になります。そのため、本番環境ではこのようなモードを常に使用しないことをお薦めします。このモードは、JDKとの互換性や開発に対してサポートされます。Oracle JVMでJMXを本番で使用する場合は、安全なJMX接続を使用する必要があります。

セキュリティ関連のプロパティ値をdbms_java.set_property、System.setPropertyまたはdbms_java.start_jmx_agentに指定する場合、非エコー・リスナーを使用するか、またはOracle Application Serverなどの安全なアプリケーション層から暗号化されたJDBC接続によってこれらを起動します。パスワードは、クリアテキスト・ファイルで保存しないでください。Oracleウォレットを使用して、証明書を作成および管理します。セキュリティを向上させるには、SSL認証のクライアント証明書を使用します。

関連項目:
Oracleデータベースのセキュリティ機能の詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください。

JMXの共有サーバーの制限事項

専用モード・サーバーでは、セッションの継続期間中のJMX接続がサポートされています。共有サーバーのJMX接続は、通常は単一のコールに限定されます。この制限は、JMX接続が本質的にスレッドやソケットなどのオペレーティング・システム・リソースに依存していることに主に起因しています。これらのリソースは、共有サーバーのコールの境界を越えて存続することはありません。したがって、単一のコールの存続期間中のみのJMX接続が完全にサポートされています。

注意:
この制限はエージェント接続にのみ影響し、それに登録されているMBeanSrverやMbeansの状態には影響しません。MBeanSrverとMbeansの状態、および特にその統計は、共有サーバーのコールの境界を越えて保持されます。

関連項目:
「共有サーバーに関する考慮事項」

専用サーバー・モードを使用できない場合でも、次のガイドラインに従って、JMX接続を確立し、共有サーバーを監視できます。

- JMXの管理アクティビティと監視アクティビティがすべて1つのJavaコールで行われるように計画します。

- DBMS_JAVA.set_propertyファンクションをコールしてcom.sun.management.jmxremote.portプロパティを設定したり、DBMS_JAVA.start_jmx_agentメソッドを使用しないでください(これらのコールによってJMXがアクティブ化され、共有サーバーのコール境界が生成されるためです)。そのかわりに、監視対象のJavaコードから直接oracle.aurora.rdbms.JMXAgent.startOJVMAgentメソッドをコールして、JMXエージェントを起動してください。com.sun.management.jmxremote.portプロパティの値をstartOJVMAgentメソッドに渡す必要があります。com.sun.management.jmxremote.portプロパティ以外のJMX関連プロパティはJMXエージェントを起動するものでなく、任意の方法を使用して設定できます。

Oracle Databaseのスレッド

Oracle JVMは、単一クライアントの非プリエンプティブ・スレッド・モデルであるデータベース・セッション・モデルに基づきます。Oracle DatabaseのJavaではスレッド・プログラムを実行できますが、実行レベルではシングル・スレッドです。このモデルのJVMは、データベース・セッションに関連するすべてのJavaスレッドを1つのオペレーティング・システム・スレッドで実行します。一度ディスパッチすると、Thread.yield()をコールしてスレッドが明示的に生成され、Socket.read()をコールしてスレッドがブロックされるまで、または実行エンジンによって切り替えられるまで、スレッドは実行を続けます。スレッドが生成され、ブロックされるか、または切り替えられると、JVMは別のスレッドをディスパッチします。

注意:
11gリリース1(11.1)以降では、Oracle JVMはスレッドの切り替えをサポートします。スレッドの切り替えはJava仕様で義務付けられていませんが、JDK1.5にある新しいjava.util.concurrent APIを適切にサポートするために必要です。

Oracle JVMには、パフォーマンスとスレッド管理を向上させるために、次の機能が追加されました。

- システム・コールを最小限に抑制します。Oracle JVMでは、標準のシステム・コールのかわりに非システム・ソリューションが採用されました。たとえば、システム・コールを使用せずにモニター同期ブロックやメソッドに入ることが可能です。

- デッドロックを検出します。

- Oracle JVMはスレッド間のデッドロックを監視します。デッドロックが発生すると、Oracle JVMはいずれかのスレッドを終了し、oracle.aurora.vm.DeadlockError例外をスローします。

- シングル・スレッド・アプリケーションは中断できません。スレッドが1つのみのアプリケーションを中断しようとすると、oracle.aurora.vm.LimboError例外がスローされます。

スレッドのライフ・サイクル

シングル・スレッド・アプリケーションでは、次のイベントの発生でコールが終了します。

- スレッドがコール元に戻された場合。

- 例外がスローされ、Javaコードで捕捉されなかった場合。

- System.exit()、OracleRuntime.exitSession()またはoracle.aurora.vm.OracleRuntime.exitCall()メソッドがコールされた場合。

- DBMS_JAVA.endsession()またはDBMS_JAVA.endsession_and_related_state()メソッドがコールされた場合。

初期スレッドが他のJavaスレッドを作成して起動した場合は、次のいずれかの方法でコールが終了します。

- メイン・スレッドがコール元に戻るか、またはこのスレッドで捕捉されない例外がスローされ、いずれの場合も、他のすべての非デーモン・スレッドは処理されます。非デーモン・スレッドは、その初期メソッドから戻されるか、スレッドで捕捉されない例外がスローされることで終了します。

- いずれかのスレッドでSystem.exit()、OracleRuntime.exitSession()またはoracle.aurora.vm.OracleRuntime.exitCall()メソッドをコールします。

- DBMS_JAVA.endsession()またはDBMS_JAVA.endsession_and_related_state()メソッドをコールします。

関連項目:
「複数のコールに影響を与えるオペレーティング・システム・リソース」。

11gリリース1(11.1)以前は、System.exit()またはoracle.aurora.vm.OracleRuntime.exitCall()をコールすることでコールが終了した場合、Oracle JVMは、専用サーバー・モードと共有サーバー・モードの両方でコールをただちに終了し、すべてのスレッドを終了していました。11gリリース1(11.1)以降では、DBMS_JAVAパッケージに次のPL/SQLファンクションを追加することでこの問題に対応しています。

- FUNCTION endsession RETURN VARCHAR2;

- FUNCTION endsession_and_related_state RETURN VARCHAR2;

関連項目:
「Javaセッションの状態に使用する2層の期間」。

コール時に、Javaプログラムが再帰的に追加のJavaコードを実行することがあります。たとえば、JDBCまたはSQLJを使用してプログラムでSQL問合せを発行すると、Javaで作成されたトリガーがコールされることがあります。コールの存続期間に関するこれまでの説明は、Javaコードへの最上位コールに関するもので、再帰的コールに関する説明ではありません。たとえば、再帰的コール内からSystem.exit()をコールすると、再帰的コールのみではなく、Javaへの最上位コール全体が終了します。

System.exit()、OracleRuntime.exitSession()およびOracleRuntime.exitCall()

System.exit()メソッドでは、Javaの状態が保持されずにJVMが終了します。これによってデータベース・セッションが終了したりクライアントが切断されることはありません。ただし、その直後にデータベース・セッション自体が終了することが頻発します。また、OracleRuntime.exitSession()でも、Javaの状態が保持されずにJVMが終了します。ただし、これによってデータベース・セッションも終了し、クライアントが切断されます。

OracleRuntime.exitCall()の動作は、OracleRuntime.threadTerminationPolicy()によって異なります。このメソッドでは、boolean値が戻されます。この値がtrueの場合、データベース・コールの終了時に、アクティブなスレッドが休止状態ではなく終了します。

- 共有サーバー・プロセスでは、threadTerminationPolicy()は常にtrueです。

- シャドウ(専用)プロセスでは、デフォルト値はfalseです。この値を変更するには、OracleRuntime.setThreadTerminationPolicy()をコールします。

- 値をfalse(デフォルト値)に設定すると、すべてのスレッドは休止状態になりますが、正常に終了するためのThreadDeath例外が発生します。

- 値がtrueの場合、すべてのスレッドがただちに終了します。

また、OracleRuntime.callExitPolicy()という別のメソッドがあります。このメソッドでは、OracleRuntime.exitSession()、OracleRuntime.exitCall()またはSystem.exit()メソッドがそれまでにコールされていない場合に、コールを終了するタイミングが決定されます。コール終了ポリシーは、OracleRuntime.setCallExitPolicy()を使用して、次のいずれかの値に設定できます。

- OracleRuntime.EXIT_CALL_WHEN_MAIN_THREAD_TERMINATES
この値に設定した場合、メイン・スレッドが戻るか、またはメイン・スレッドで捕捉されない例外が発生するとすぐに、デーモンおよび非デーモンの両方を含む残りのすべてのスレッドは次の状態になります。

- 共有サーバー・モードでは、threadTerminationPolicy()がtrueの場合、常に停止します。

- threadTerminationPolicy()がfalseの場合、休止状態になります。

- OracleRuntime.EXIT_CALL_WHEN_ALL_NON_DAEMON_THREADS_TERMINATE
これはデフォルト値です。この値が設定されると、デーモン・スレッドのみが実行中である場合にコールが終了します。この時点では次のようになります。

- threadTerminationPolicy()がtrueの場合、共有サーバー・モードでは、デーモン・スレッドは常に停止します。

- threadTerminationPolicy()がfalseの場合、デーモン・スレッドは次のコールまで休止状態になります。これは、シャドウ(専用)サーバー・モードのデフォルト設定です。

- OracleRuntime.EXIT_CALL_WHEN_ALL_THREADS_TERMINATE
この値に設定した場合、すべてのスレッドが戻るか、捕捉されない例外が原因で終了する場合のみ、コールは終了します。この時点では、threadTerminationPolicy()の値に関係なくコールが終了します。

注意:
Oracleデータベース9.x以前のデータベース・リリースでは、JVMはcallExitPolicy()がOracleRuntime.EXIT_CALL_WHEN_ALL_NON_DAEMON_THREADS_TERMINATEであり、共有サーバー・プロセスと専用サーバー・プロセスの両方でthreadTerminationPolicy()がtrueであるかのように動作します。これは、この時点でデーモン・スレッドが停止することを意味します。また、exitCall()が実行された場合、共有および専用サーバー・プロセスの両方で、コールの終了前にすべてのスレッドが停止します。

共有サーバーに関する考慮事項

注意:
パフォーマンス上の理由から、専用サーバーをお薦めします。また、専用サーバーでは、複数のコールにわたって保持されるスレッドおよびソケットに依存するアプリケーションのクラスをサポートしています。たとえば、JMXエージェント接続機能などです。JMXエージェントの詳細は、「JMXを使用したアプリケーションの管理」を参照してください。

共有サーバーを使用するセッションでは、複数のコールにわたる制限が存在します。これは、共有サーバーを使用するセッションは、後続のデータベース・コールによる同一プロセスへの接続が保証されていないためで、したがって、複数コールにわたって保持する必要があるセッション固有のメモリーおよびオブジェクトは、SGAに保存されます。つまり、スレッド、オープン・ファイルおよびソケットなどのプロセス固有のリソースは、各コールの終了時にクリーン・アップする必要があるため、次のコールでは使用できません。

この項の内容は、次のとおりです。

- コール終了時の移行

- コール終了時の最適化に対するOracle固有のサポート

- EndOfCallRegistry.registerCallback()メソッド

- EndOfCallRegistry.runCallbacks()メソッド

- Callbackインタフェース

- Callback.act()メソッド

- 複数のコールに影響を与えるオペレーティング・システム・リソース

コール終了時の移行

共有サーバー・モードの場合、Oracle Databaseでは、Javaプログラムの状態を次のコールまで保持するために、コール終了時にstatic変数から参照可能なすべてのオブジェクトがセッション・スペースに移行されます。セッション・スペースはクライアントのセッション内にあり、複数コールにわたって存続するstatic変数およびオブジェクトが格納されます。この移行処理は、各コールの終了時にOracle JVMで自動的に実行されます。

この移行処理にはメモリーが使用され、パフォーマンスにも影響します。したがって、複数のコールにわたって保持するstatic変数やオブジェクトは最小限に抑えるように注意してください。static変数にオブジェクトを不要に格納すると、メモリー・マネージャが移行処理を実行し、セッションごとにリソースを使用することになるため、不要な負担がかかります。static変数を必要最低限に抑えることで、メモリー・マネージャの負担を軽減し、サーバーのパフォーマンスを向上させることができます。

Javaプログラムを同時に実行できるユーザー数を最大にするには、セッションのフットプリントを最小にすることが重要です。特に、拡張性を最大にするには、非アクティブなセッションが占有するメモリー領域を必要最小限にする必要があります。フットプリントを最小化する簡単な方法は、コール終了ごとに大きなデータ構造を解放することです。多くのデータ構造は、別のコールで再度必要になったときに遅延して再作成できます。このような理由から、Oracle JVMには、コール終了時など、セッションが非アクティブになる直前に、指定のJavaメソッドをコールするためのメカニズムがあります。

このメカニズムは、EndOfCallRegistry通知と呼ばれます。これによって、コール終了時にstatic変数を消去し、次のコールの着信時に遅廷初期化テクニックを使用して変数を再初期化できます。これは、複数コール間で保持するためにメモリー・マネージャが必要としている記憶域の容量に懸念がある場合のみ実行してください。Javaで実装する複雑でステートフルなサーバー・アプリケーションの場合のみ、懸念することになります。

コール終了時にデータ構造をNULLにリセットし、その後新しいコールごとにデータ構造を再作成するかどうかの決定は、時間と領域のトレードオフの問題です。データ構造の再作成によって処理時間は多少長くなりますが、次のコールまでデータ構造を保持する必要がないため、メモリー領域をかなり節約できます。また、セッション領域に移行されたオブジェクト(特に大型のオブジェクト)のアクセスには時間がかかり、効率が悪くなります。これは、セッションの表現がコール領域に基づくオブジェクトとは異なることに起因しています。

このような最適化の対象として、次のデータ構造があります。

- バッファまたはキャッシュ。

- 静的フィールド(配列など)。これは、一度初期化するとプログラムの実行が完了するまで変化しません。

- コール間の領域使用効率およびコール中の速度効率の向上が期待できる、動的に作成されるデータ構造。これによってコードが複雑になり、管理が困難になることもあります。したがって、労力に見合う程度の領域が節約される場合のみ、これの実施を検討してください。

コール終了時の最適化に対するOracle固有のサポート

コール終了時に消去するstatic変数は、バッファ、フィールドまたはデータ構造の作成時に登録できます。oracle.aurora.memoryManager.EndOfCallRegistryクラスでは、registerCallback()メソッドによって、Callbackオブジェクトを実装するオブジェクトが取得されます。registerCallback()メソッドには、このオブジェクトがコール終了時まで格納されます。コール終了時に、Oracle JVMは登録されたすべてのCallbackオブジェクトのact()メソッドをコールします。Callbackオブジェクト内のact()メソッドは、ユーザー定義のバッファ、フィールドまたはデータ構造を消去するために実装されます。消去されると、Callbackオブジェクトはレジストリから削除されます。

注意:
コール終了時がセッションの終了時でもある場合は、いずれにしてもセッション・スペースが消去されるため、コールバックは開始されません。

弱い表では、エンドオブコール・コールバックのレジストリが保持されます。Callbackオブジェクトまたは値のいずれかがJavaプログラムから参照できない場合は、オブジェクトと値の両方が表から削除されます。弱い表を使用してコールバックを保持すると、コールバックを登録しても、ガベージ・コレクタによるオブジェクトの削除は回避されません。したがって、必要なコールバックを自分で保持する必要があり、表に保持しておくことはできません。

EndOfCallRegistryの使用方法は、操作対象のオブジェクトがstaticフィールドに保持されているか、インスタンス・フィールドに保持されているかによって異なります。

静的フィールド

EndOfCallRegistryを使用して、クラス全体に対応付けられた状態を消去します。この場合、Callbackオブジェクトはprivate staticフィールドに保持する必要があります。コール間で削除されたキャッシュ内のデータにアクセスする必要があるコードは、キャッシュ・データを遅延して作成または再作成するメソッドをコールする必要があります。

次の例を考えてみます。

import oracle.aurora.memoryManager.Callback;
import oracle.aurora.memoryManager.EndOfCallRegistry;

class Example
{
static Object cachedField = null;
private static Callback thunk = null;

static void clearCachedField()
{
// clear out both the cached field, and the thunk so they don't
// take up session space between calls
cachedField = null;
thunk = null;
}

private static Object getCachedField()
{
if (cachedField == null)
{
// save thunk in static field so it doesn't get reclaimed
// by garbage collector
thunk = new Callback () {
public void act(Object obj)
{
Example.clearCachedField();
}
};

// register thunk to clear cachedField at end-of-call.
EndOfCallRegistry.registerCallback(thunk);
// finally, set cached field
cachedField = createCachedField();
}
return cachedField;
}

private static Object createCachedField()
{
...
}
}

この例では、次の手順が実行されます。

1. staticフィールドthunkにCallbackオブジェクトを作成します。

2. このCallbackオブジェクトをコール終了時の移行に登録します。

3. Callback.act()メソッドを実装して、Callbackオブジェクト自体も含めて、すべてのstatic変数を解放します。

4. キャッシュを遅延して再作成するためのcreateCachedField()メソッドを指定します。

ユーザーがキャッシュを作成すると、CallbackオブジェクトがgetCachedField()メソッドに自動的に登録されます。コール終了時に、Oracle JVMは、登録されたCallback.act()メソッドをコールして、静的メモリーを解放します。

インスタンス・フィールド

インスタンス・フィールドに保持されているデータ構造を消去状態にするには、EndOfCallRegistryを使用します。たとえば、状態があるクラスの各インスタンスに対応付けられている場合、各インスタンスにはそのインスタンスのキャッシュ状態を保持するフィールドがあり、必要に応じてキャッシュ・フィールドが埋められます。状態が確実にキャッシュされるメソッドを使用してキャッシュ・フィールドにアクセスできます。

次の例を考えてみます。

import oracle.aurora.memoryManager.Callback;
import oracle.aurora.memoryManager.EndOfCallRegistry;

class Example2 implements Callback
{
private Object cachedField = null;

public voidact (Object obj)
{
// clear cached field
cachedField = null;
obj = null;
}

// our accessor method
private static Object getCachedField()
{
if (cachedField == null)
{
// if cachedField is not filled in then you must
// register self, and fill it in.
EndOfCallRegistry.registerCallback(self);
cachedField = createCachedField();
}
return cachedField;
}

private Object createCachedField()
{
...
}
}

この例では、次の手順が実行されます。

1. インスタンスをCallbackオブジェクトとして実装します。

2. Callback.act()メソッドを実装して、インスタンス・フィールドを解放します。

3. ユーザーがキャッシュを要求すると、Callbackオブジェクトによって、このオブジェクト自体がコール終了時の移行に登録されます。

4. キャッシュを遅延して再作成するためのcreateCachedField()メソッドを指定します。

ユーザーがキャッシュを作成すると、CallbackオブジェクトがgetCachedField()メソッドに自動的に登録されます。コール終了時に、Oracle JVMは、登録されたCallback.act()メソッドをコールして、キャッシュを解放します。

この方法を使用すると、Callbackオブジェクトとそのインスタンスが同じオブジェクトになるため、オブジェクトの存続期間とそのインスタンスの存続期間が等しくなります。

EndOfCallRegistry.registerCallback()メソッド

registerCallback()メソッドは、Callbackオブジェクトをレジストリにインストールします。コール終了時に、Oracle JVMは登録されたすべてのCallbackオブジェクトのact()メソッドをコールします。

Callbackオブジェクトは、自動的に、またはObjectインスタンスを使用して登録できます。オブジェクトに格納されたその他の情報をact()に渡す必要がある場合は、このオブジェクトを、Objectのインスタンスであるvalueパラメータに登録できます。

registerCallback()メソッドの有効なシグネチャは、次のとおりです。

public static void registerCallback(Callback thunk, Object value);

public static void registerCallback(Callback thunk);

次の表に、registerCallbackのパラメータとその説明を示します。

パラメータ

説明

thunk

コール終了時の移行でコールされるCallbackオブジェクトを示します。

value

オブジェクトに格納されたその他の情報をact()に渡す必要がある場合は、このオブジェクトをvalueパラメータに登録できます。場合によっては、コールバックに必要な状態の保持にvalueパラメータが必要になります。ただし、大半のユーザーは、このパラメータの値を指定する必要はありません。

EndOfCallRegistry.runCallbacks()メソッド

runCallbacks()メソッドのシグネチャは、次のとおりです。

static void runCallbacks()

JVMはコール終了時にこのメソッドをコールし、registerCallback()を使用して登録されたすべてのCallbackオブジェクトごとにact()をコールします。コール終了時にこれがコールされた後で、オブジェクトが移行され、最終ステップが行われます。

注意:
このメソッドは、作成したコード内ではコールしないでください。

Callbackインタフェース

インタフェースの宣言は、次のとおりです。

Interface oracle.aurora.memoryManager.Callback

EndOfCallRegistry.registerCallback()を使用して登録するオブジェクトは、Callbackインタフェースを実装する必要があります。このインタフェースは、アプリケーションで、コール終了時に通知が必要な場合に役立ちます。

Callback.act()メソッド

act()メソッドのシグネチャは、次のとおりです。

public void act(Object value)

コールの終了時に実行する必要がある任意のアクティビティを実装できます。通常、このメソッドにはセッション・スペースに保存されるメモリーを消去するプロシージャが含まれます。

複数のコールに影響を与えるオペレーティング・システム・リソース

次の表に示すとおり、共有サーバー・モードでは、データベース・コールの終了時にOracle JVMが、オープン状態のオペレーティング・システム・リソースをすべてクローズします。

リソース

存続期間

ファイル

データベースのコールが終了すると、オープン状態のすべてのファイルがクローズされます。

スレッド

コールが終了すると、すべてのスレッドが終了します。

ソケット

- クライアント・ソケットは複数コールにわたって存続できます。

- サーバー・ソケットは、コールが終了すると終了します。

オペレーティング・システム・リソースに依存するオブジェクト

Javaオブジェクトの有効期間は、そのオブジェクトの使用可能期間に関係なく、セッションが存続している期間になります。たとえば、staticクラス変数あるいはこのクラスを直接または間接的に参照するクラス変数にJavaオブジェクトを格納すると、セッション終了まで有効になります。使用可能期間の終了後にJavaオブジェクトを使用しようとすると、Oracle Databaseから例外がスローされます。これは次のような例に当てはまります。

- 前のコールの終了時にクローズしたjava.io.FileInputStreamから読み取ろうとすると、java.io.IOExceptionが発生します。

- 以前のコールで実行したThreadオブジェクトが後続のコールでもアクセス可能な場合は、java.lang.Thread.isAlive()がfalseになります。

1つのコールの終了時には、そのコールに対してローカルなリソースをクローズしてください。ただし、オペレーティング・システム・リソースを保持するstaticオブジェクトについては、これらのリソースがコール終了後に受ける影響を考慮する必要があります。

ファイル

共有サーバー・モードでは、コールが終了すると、Oracle JVMはオープン状態のオペレーティング・システム構成メンバーを自動的にクローズします。これは、Javaオブジェクト内のオペレーティング・システム・リソースすべてに影響を与えます。static変数の中でファイルをオープンした場合、そのファイル・ハンドルはコールの終了時にクローズされます。したがって、複数のコールにまたがってFileオブジェクトを保持すると、次にファイル・ハンドルを使用するときに例外がスローされます。

例2-5のConcatクラスは、複数のファイルを1つのファイルoutFileに書き込むことができます。最初のコールでoutFileが作成されます。最初の入力ファイルがオープンされ、読み取られてoutFileに記録され、コールが終了します。outFileはstatic変数として定義されているため、次のコールが起動される間にセッション・スペースに移動します。ただし、ファイル・ハンドルは、コールが終了するとクローズします。次回addFile()をコールすると、例外が発生します。

例2-5 オペレーティング・システム・リソースの調整

public class Concat
{
static File outFile = new File("outme.txt");
FileWriter out = new FileWriter(outFile);

public static void addFile(String[] newFile)
{
File inFile = new File(newFile);
FileReader in = new FileReader(inFile);
int i;

while ((i = in.read()) != -1)
out.write(i);
in.close();
}
}

これには対処法があります。コールが終了するたびにファイルやバッファなどをクローズし、次のコールの開始時にリソースを再度オープンして、ハンドルを有効な状態に維持します。もう1つの方法は、オペレーティング・システム・リソースではなくデータベースを使用することです。たとえば、ファイルではなくデータベース表を使用します。あるいは、複数のコールにわたって存続するstaticオブジェクトにオペレーティング・システム・リソースを格納しないようにします。かわりに、そのコールに対するローカルなオブジェクトの中でのみ、オペレーティング・システム・リソースを使用します。

例2-6に、例2-5の場合のようにオペレーティング・システム・リソースを調整せずに連結する方法を示します。addFile()メソッドは、各コールでoutme.txtファイルをオープンし、そのファイルに書き込まれた内容がすべて最後に追加されていることを確認します。このファイルは、各コールの終了時にクローズします。この場合、次の2つの状態が発生します。

- Fileオブジェクトはコール外では存続しなくなります。

- オペレーティング・システム・リソースであるoutme.txtファイルはコールごとに再度オープンされます。Fileオブジェクトをstatic変数に指定した場合は、各コール内でoutme.txtをクローズすることで、オペレーティング・システム・リソースを調整する必要はなくなります。

例2-6 オペレーティング・システム・リソースの正しい管理

public class Concat
{

public static void addFile(String[] newFile)
{
/*open the output file each call; make sure the input*/
/*file is written out to the end by making it "append=true"*/
FileWriter out = new FileWriter("outme.txt", TRUE);
File inFile = new File(newFile);
FileReader in = new FileReader(inFile);
int i;

while ((i = in.read()) != -1)
out.write(i);
in.close();

/*close the output file between calls*/
out.close();
}
}

ソケット

ソケットは、クライアントとサーバー間の接続をセットアップするために使用されます。データベース接続ごとに、接続の片側でソケットが使用されます。接続のセットアップはアプリケーションでは行われません。接続は、基礎となるプロトコル(Oracle NetのTTCまたはIIOP)で実行されます。

関連項目:
接続の構成方法については、「Oracle JVMの構成」を参照してください。

データベースに格納された1つのクラス内から指定のURLに接続するなど、別の接続をセットアップすることもできます。このセットアップでは、次のコンストラクタを使用して接続のクライアント側とサーバー側に対応するようにソケットをインスタンス化します。

- java.net.Socket()コンストラクタで、クライアント・ソケットを作成します。

- java.net.ServerSocket()コンストラクタで、サーバー・ソケットを作成します。

ソケットは接続の両側にあります。着信コールをリスニングするサーバー側の接続に対応するのはServerSocketインスタンスです。要求を送るクライアント側の接続に対応するのはSocketインスタンスです。JVMに定義されたソケットは、共有サーバー内のServerSocketインスタンスは複数のコールにまたがって存続できないという制限の範囲内で使用できます。

次の表に、ソケットの種類とその説明を示します。

ソケットの種類

説明

Socket

接続のクライアント側は送信側になるため、Socketインスタンスは共有サーバー内の複数のコールにわたって対応できます。

ServerSocket

接続のサーバー側のリスナーです。ServerSocketインスタンスは、共有サーバー内の1つのコールが終了するとクローズします。共有サーバーはコールの終了時に別のクライアントに移動します。作成元以外のコールでServerSocketインスタンスを使用すると、ソケットがクローズしていることを示すI/O例外が発生します。

スレッド

共有サーバー・モードでは、戻りまたは捕捉されない例外が原因でコールが終了すると、Oracle JVMは、すべてのデーモン・スレッドでThreadDeathExceptionをスローします。このThreadDeathExceptionは、原則的にスレッドの実行を停止します。複数のコールにわたって存続するスレッドに依存しているコードは、共有サーバー・モードでは予測どおりには動作しません。たとえば、データベース・コールの終了時にはすべてのスレッドが停止するため、スレッドの初期化を追跡するstatic変数の値は、後続のコールでは正確さに欠ける可能性があります。

具体的な例として、標準のRMIサーバーは共有サーバー・モードで機能します。ただし、1つのコールのコンテキスト内のみで有効です。これは、共有サーバー・モードでRMIサーバーがデーモン・スレッドをフォーク処理し、コール終了時に停止するためです。つまり、すべての非デーモン・スレッドが戻ったときにデーモン・スレッドが停止します。後続のコールでRMIサーバー・セッションを再び開始しても、これらのデーモン・スレッドは再開されないため、RMIサーバーは適切に機能しません。

3 Oracle DatabaseでのJavaメソッドのコール

この章では、Oracle Database内でJavaメソッドをコールする方法の概要および例を示します。内容は次のとおりです。

- Javaメソッドの起動

- サーバー上での実行を識別する方法

- サーバー上の出力のリダイレクト

- データベースでのJavaの直接コール

Javaメソッドの起動

Javaアプリケーションのタイプによって、クライアントがJavaメソッドをコールする方法が決まります。次の項では、Javaメソッドのコールに使用できる各Java Application Programming Interface(API)について説明します。

- PL/SQLラッパーの使用

- JNIサポート

- データベースでのSQLJおよびJDBCとJavaの併用

- コマンドライン・インタフェースの使用

- クライアント側スタブの使用

PL/SQLラッパーの使用

Javaストアド・プロシージャは、PL/SQLストアド・プロシージャと同じ方法で実行できます。Oracle Databaseでは、通常、JavaはPL/SQLインタフェースを介して起動します。

Javaストアド・プロシージャをコールするには、コール仕様を使用して公開する必要があります。次の例は、文字列を戻す簡単なJavaストアド・プロシージャを作成、解決、ロードおよび公開する方法を示しています。

1. クラスHelloを次のように定義します。

public class Hello
{
public static String world()
{
return "Hello world";
}
}

ファイルをHello.javaファイルとして保存します。

2. クライアント・システムで、標準Javaコンパイラを使用して、次のようにクラスをコンパイルします。

javac Hello.java

CLASSPATHは、特に、シェル・スクリプトまたはMakeファイルの作成時にはjavacコマンドを使用してコマンドラインで指定することをお薦めします。Javaコンパイラによって、Javaバイナリ・ファイル(この例の場合はHello.class)が生成されます。

このJavaコードの実行場所を決定する必要があります。クライアント・システムでHello.classを実行すると、Hello.classの実行に必要なすべてのサポートされるコア・クラスがCLASSPATHで検索されます。この結果、次のいずれかで依存クラスが検索されます。

- 1つ以上のディレクトリ内の個々のファイル。このディレクトリはCLASSPATHで指定されます。

- .jarまたは.zipファイル内。このファイルを含むディレクトリはCLASSPATHで指定されます。

3. Helloクラスに使用するリゾルバを決定します。
この例の場合、サーバーでJavaスキーマ・オブジェクトとしてデータベースに格納される、Hello.classをサーバーにロードします。world()メソッドをコールすると、Oracle JVMでは、リゾルバを使用して、Stringなどの必要なサポート・クラスを検索します。この場合、Oracle JVMでは、デフォルトのリゾルバを使用します。デフォルトのリゾルバは、最初に現行スキーマ内、次にPUBLIC内でクラスを検索します。java.langパッケージなど、すべてのコア・クラス・ライブラリはPUBLIC内にあります。別のリゾルバを指定する必要がある場合があります。loadjavaツールの使用時に解決を強制的に実行すると、実行時以前に問題をトレースできます。

関連項目:
「クラス依存関係の解決」と第12章「スキーマ・オブジェクトおよびOracle JVMユーティリティ」

4. loadjavaツールを使用して、サーバー上にクラスをロードします。ユーザー名とパスワードを指定する必要があります。loadjavaツールを次のように実行します。

loadjava -user HR Hello.class
Password: password

5. コール仕様を使用してストアド・プロシージャを公開します。
Java staticメソッドをSQLコールでコールするには、コール仕様を使用してメソッドを公開する必要があります。コール仕様では、メソッドで使用する引数およびメソッドで戻されるSQL型が定義されます。

SQL*Plusでは、次のようにデータベースに接続し、Hello.world()に対するトップレベルのコール仕様を定義します。

sqlplus HR
Enter password: password
connected
SQL> CREATE OR REPLACE FUNCTION helloworld RETURN VARCHAR2 AS
2  LANGUAGE JAVA NAME 'Hello.world () return java.lang.String';
3  /
Function created.

6. ストアド・プロシージャを次のようにコールします。

SQL> VARIABLE myString VARCHAR2(20);
SQL> CALL helloworld() INTO :myString;
Call completed.
SQL> PRINT myString;

MYSTRING
---------------------------------------
Hello world

SQL>

call helloworld() into :myString文によって、Oracle Databaseでトップレベルのコールが実行されます。SQLおよびPL/SQLでは、作成言語がJava、PL/SQLまたは他の言語のいずれであるかによってストアド・プロシージャが区別されることはありません。コール仕様は、言語間コールを一貫した方法で結び付ける手段です。コール仕様は、トリガーまたはSQLコールやPL/SQLコールでコールされるエントリ・ポイントのみに必要です。さらに、JDeveloperを使用してコール仕様を自動的に作成することもできます。

関連項目:
第5章「Javaストアド・プロシージャの開発」

JNIサポート

Javaネイティブ・インタフェース(JNI)は、Javaネイティブ・メソッドの作成、およびJVMのネイティブ・アプリケーションへの埋込みを行うための標準プログラミング・インタフェースです。JNIの主要目的は、プラットフォーム固有のネイティブ・ライブラリを使用するJavaアプリケーションのバイナリ互換性を提供することです。

Oracle Databaseでは、JavaアプリケーションにおけるJNIの使用はサポートされていません。JNIを使用する場合、アプリケーションが100パーセントPure Javaではないため、ネイティブ・メソッドをプラットフォーム間で移植する必要があります。ネイティブ・メソッドを使用すると、サーバーのクラッシュ、セキュリティ違反およびデータ破損などの問題が発生する可能性があります。

データベースでのSQLJおよびJDBCとJavaの併用

SQLJおよびJava Database Connectivity(JDBC)APIは、Javaクライアントから使用できます。この2つのAPIにより、指定したユーザー名とパスワードを使用してデータベース上でセッションが確立され、データベースに対するSQL問合せが実行されます。次の表に、APIとその説明を示します。

API

説明

JDBC

比較的複雑または動的なSQL問合せの場合に、このAPIを使用します。JDBCでは、セッションの確立、問合せの作成などをユーザーが実行する必要があります。

SQLJ

簡単で静的および動的なSQL問合せの場合に、このAPIを使用します。SQLJは、通常、既知の列名を持つ既知の表に対して実行されます。

この項の内容は、次のとおりです。

- JDBC

- SQLJ

- JDBCとSQLJの比較例

- 完全なSQLJの例

- SQLJの強い型指定

- SQLJプログラムの変換

- サーバー上でのSQLJプログラムの実行

- サーバー上で実行するためのクライアント・アプリケーションの変換

- PL/SQLとの対話

JDBC

JDBCは業界標準のAPIであり、SQL文をJavaメソッドの引数として埋め込むことができます。JDBCはX/OpenのSQL Call Level Interface(CLI)に基づき、SQL92標準のエントリ・レベルに準拠しています。オラクル社などの各ベンダーは、標準のjava.sqlパッケージのインタフェースを実装することによって、独自のJDBC実装を作成しています。Oracleには、これらの標準インタフェースを実装する次のJDBCドライバが用意されています。

- JDBC Thinドライバ。クライアント側のアプリケーションまたはアプレットに使用でき、Oracleクライアントのインストールを必要としない100パーセントPure Javaのソリューションです。

- JDBC OCIドライバ。クライアント側のアプリケーションに使用するドライバで、Oracleクライアントのインストールが必要です。

- サーバー側JDBCドライバ。Oracle Databaseに埋め込まれています。

JDBCを使用する場合は、次のタスクを順番に実行します。

1. 接続ハンドルを取得します。

2. 目的のSQL操作に使用する文オブジェクトを作成します。

3. SQL操作にバインドするローカル変数を代入します。

4. 操作を実行します。

5. オプションで結果セットを取得します。

多くのアプリケーションではこの方法で十分ですが、複雑な文の場合は作業が煩雑になります。動的なSQL操作の場合は、実行時まで操作内容がわからないため、JDBCを使用する必要があります。ただし、典型的なアプリケーションでは、このSQL操作はあまり採用されていません。

関連項目:
『Oracle Database JDBC開発者ガイド』

SQLJ

SQLJには、1回の手順で静的なSQL操作をJavaソース・コードに直接埋め込む業界標準の方法が用意されているため、JDBCのような複数の手順は不要です。Oracle SQLJは、米国規格協会(ANSI)規格X3H2-98-320に準拠しています。

SQLJは、標準のSQLJプログラミング構文をサポートするプリコンパイラであるトランスレータとランタイム・コンポーネントで構成されています。SQLJソース・コードを.sqljファイルに作成した後、トランスレータを使用して処理します。トランスレータでは、SQLJソース・コードが標準Javaソース・コードに変換され、SQL操作がSQLJランタイム・コールに変換されます。Oracle DatabaseのSQLJ実装では、トランスレータがJavaコンパイラをコールして、Javaソース・コードをコンパイルします。SQLJアプリケーションを実行すると、SQLJランタイムがJDBCをコールして、データベースと通信します。

また、SQLJを使用すると、実行時前にSQL文のエラーを捕捉できます。JDBCコードは、Pure Javaであるため、直接コンパイルされます。コンパイラでは、SQLエラーを検出できません。これに対して、SQLJコードの変換時に、トランスレータでは、埋め込まれているSQL文のセマンティクスおよび構文を解析するため、SQLエラーが開発時に捕捉され、アプリケーションの実行時にエンド・ユーザーによってエラーが捕捉されることはありません。

関連項目:
『Oracle Database SQLJ開発者ガイド』

JDBCとSQLJの比較例

次は、単純な操作を実行するJDBCコードとSQLJコードの例です。

JDBC:

// Assume you already have a JDBC Connection object conn
// Define Java variables
String name;
int id=37115;
float salary=20000;

// Set up JDBC prepared statement.
PreparedStatement pstmt = conn.prepareStatement
("SELECT first_name FROM employees WHERE employee_id=? AND salary>?");
pstmt.setInt(1, id);
pstmt.setFloat(2, salary);

// Execute query; retrieve name and assign it to Java variable.
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
name=rs.getString(1);
System.out.println("Name is: " + name);
}

// Close result set and statement objects.
rs.close()
pstmt.close();

JDBC接続connがすでに確立されていると仮定しています。次の手順を実行する必要があります。

1. Javaの変数name、idおよびsalaryを定義します。

2. PreparedStatementインスタンスを作成します。
SQL文内の値を動的に設定する必要がある場合はいつでも、プリコンパイルされたSQL文を使用できます。異なる変数値を設定して、同じプリコンパイルされたSQL文を繰返し使用できます。プリコンパイルされたSQL文中の疑問符(?)は、Java変数用のプレースホルダです。前述の例では、これらの変数には、pstmt.setInt()およびpstmt.setFloat()メソッドを使用して値が割り当てられます。最初の「?」は、int変数idを参照し、値は37115に設定されます。2番目の「?」は、float変数salaryを参照し、値は20000に設定されます。

3. 問合せを実行し、データをResultSetオブジェクトに戻します。

4. ResultSetオブジェクトから目的のデータを取り出し、表示します。この場合は、first_name列です。この例では1行のみですが、通常結果セットには複数行のデータが含まれます。

SQLJ:

String name;
int id=37115;
float salary=20000;
#sql {SELECT first_name INTO :name FROM employees WHERE employee_id=:id AND salary>:salary};
System.out.println("Name is: " + name);

SQLJでは、SQL文を直接Javaコードに埋め込めることに加え、バインド式とも呼ばれる、SQL文で直接使用できるJavaホスト式をサポートしています。最も単純なホスト式は、この例のような単純な変数です。ただし、比較的複雑な式も使用できます。ホスト式の前には、コロン(:)を置きます。この例で使用されているJavaホスト式は、name、idおよびsalaryです。SQLJではホスト式をサポートしているため、単一行のデータのみを戻す場合は、結果セットなどは不要です。

注意:
SQLJ文は宣言も含めすべて、#sqlトークンで始まります。

完全なSQLJの例

この項では、単純なSQLJプログラムの完全な例を示します。

import java.sql.*;
import sqlj.runtime.ref.DefaultContext;
import oracle.sqlj.runtime.Oracle;

#sql iterator MyIter (String first_name, int employee_id, float salary);

public class MyExample
{
public static void main (String args[]) throws SQLException
{
Oracle.connect("jdbc:oracle:thin:@localhost:5521:orcl", "HR", "<password>");
#sql { INSERT INTO employees (first_name, employee_id, salary) VALUES ('SMITH', 32, 20000) };
MyIter iter;
#sql iter={ SELECT first_name, employee_id, salary FROM employees };
while (iter.next())
{
System.out.println(iter.first_name()+" "+iter.employee_id()+" "+iter.salary());
}
}
}

この例では、次の手順を実行します。

1. イテレータを宣言します。
SQLJでは、イテレータと呼ばれる強い型指定のJDBC結果セットが使用されます。イテレータには、特定のデータ型に使用される特定数の列があります。この例のように、イテレータを使用する前に、イテレータの型を定義する必要があります。

#sql ITERATOR MyIter (String first_name, int employee_id, float salary);

この宣言によって、SQLJではイテレータ・クラス、MyIterが作成されます。MyIter型のイテレータでは、Java Stringにマップされる最初の列の結果、Java intにマップされる2番目の列の結果、およびJava floatにマップされる3番目の列の結果を格納できます。この定義では、3つの列にfirst_name、employee_idおよびsalaryという名前が付けられ、データベース内の参照表の列名と照合されます。MyIterは、名前付きイテレータです。

2. データベースに接続します。

Oracle.connect("jdbc:oracle:thin:@localhost:5521:orcl","HR", "<password>");

SQLJには、Oracleクラスがあり、そのconnect()メソッドを使用して次の重要なタスクが実行されます。

1. データベースにアクセスするためにSQLJが使用するOracle JDBCドライバ(この場合は、JDBC Thinドライバ)を登録します。

2. 指定のURLにある指定したスキーマ(この場合は、指定されたパスワードを持つユーザーHR)のデータベース接続をオープンします。この場合は、URLはホストlocalhost、ポート5521およびSID orclを指し示しています。

3. この接続をSQLJ文のデフォルト接続として確立します。JDBC文では接続オブジェクトを明示的に指定する必要がありますが、SQLJ文ではデフォルト接続を暗黙的に使用するか、または必要に応じて別の接続を指定できます。

3. SQL文を処理します。次の操作が実行されます。

1. 行をemployees表に挿入します。

#sql {INSERT INTO employees (first_name, employee_id, salary) VALUES ('SMITH', 32, 20000)};

2. 次のイテレータがインスタンス化および移入されます。

MyIter iter;
#sql iter={SELECT first_name, employee_id, salary FROM employees};

4. イテレータ内に移入されたデータにアクセスします。

while (iter.next())
{
System.out.println(iter.first_name()+" "+iter.employee_id()+" "+iter.salary());
}

next()メソッドはすべてのイテレータに共通で、JDBC結果セットのnext()メソッドと同じ役割を果し、残りの行がある場合はtrueを戻し、次の行のデータに移動します。列名と名前が一致するイテレータのアクセッサ・メソッドをコールすることで、各行のデータにアクセスできます。これは、すべての名前付きイテレータの特性です。この例では、メソッドfirst_name()、employee_id()およびsalary()を使用してデータにアクセスします。

SQLJの強い型指定

SQLJでは、結果セットではなく、イテレータのような強い型指定を使用します。これによって、変換時にSQL命令をデータベースに照合してチェックできます。たとえば、SQLJでは、データベースに接続し、問合せ対象のデータベース表と照合して各自のイテレータをチェックできます。トランスレータでは、これらの一致が確認されるため、変換時にSQLエラーを捕捉でき、確認されない場合、エラーはアプリケーションの実行時まで捕捉されません。さらに、スキーマを後で変更した場合、トランスレータを再実行することによって、変更内容がアプリケーションに影響を与えるかどうかを確認できます。

SQLJプログラムの変換

Oracle JDeveloperなどの統合開発環境(IDE)では、作成時に、SQLJプログラムを変換、コンパイルおよびカスタマイズできます。Oracle JDeveloperは、Microsoft社のWindowsに対応したJavaプログラミング用のビジュアル開発環境です。IDEを使用しない場合は、フロントエンドのSQLJユーティリティsqljを使用します。このユーティリティは次のように実行できます。

%sqlj MyExample.sqlj

SQLJトランスレータでは、SQL操作の構文とセマンティクスがチェックされます。オンライン・チェックを使用して、操作をデータベースに照合してチェックできます。これを行う場合は、トランスレータ・オプションの設定に、サンプル・データベース・スキーマを指定する必要があります。スキーマのデータは、プログラムで最終的に実行されるスキーマのデータと同一である必要はありません。ただし、表には対応する名前とデータ型を持つ列が含まれている必要があります。次の例のように、ユーザー・オプションを使用してオンライン・チェックを使用可能にし、スキーマのユーザー名、パスワードおよびURLを指定します。

%sqlj -user=HR@jdbc:oracle:thin:@localhost:5521:orcl MyExample.sqlj
Password: password

サーバー上でのSQLJプログラムの実行

クライアント上では多くのSQLJアプリケーションが実行されます。ただし、SQLJは、通常サーバー上で実行するSQL集中型のストアド・プロシージャのプログラミングに優れた効果を発揮します。

クライアント側SQLJプログラムとサーバー側SQLJプログラムの作成に違いはほとんどありません。SQLJランタイム・パッケージはサーバー上で自動的に使用できます。ただし、次の点も考慮する必要もあります。

- サーバー上でコードを実行する場合、明示的なデータベース接続はありません。暗黙的な接続が1つあるのみです。通常の接続コードは必要ありません。既存のクライアント側アプリケーションを移植する場合、接続コードは無視されるため、コードを削除する必要はありません。

- サーバー側JDBC内部ドライバは、自動コミット機能をサポートしていません。トランザクションの手動コミットおよびロールバックには、SQLJ構文を使用します。

- サーバーでのデフォルトの出力デバイスは、ユーザー・スクリーンではなくトレース・ファイルです。デプロイされているサーバー・アプリケーションのSystem.outには書き込むことがないため、通常、これは開発時のみの問題です。

サーバーでSQLJプログラムを実行し、クライアント上にコードが作成されている場合は、次の2つのオプションがあります。

- クライアント上のSQLJソース・コードを変換し、Javaのクラスやリソースなどの個々のコンポーネントをサーバー上にロードします。この場合、最初にクラスやリソースを.jarファイルにまとめてから、サーバー上にロードすると簡単です。

- 埋め込まれているトランスレータで変換するSQLJソース・コードをサーバー上にロードします。

いずれの場合も、loadjavaツールを使用してサーバーにファイル(複数可)をロードします。

サーバー上で実行するためのクライアント・アプリケーションの変換

既存のSQLJクライアント側アプリケーションを変換してサーバー上で実行するには、そのアプリケーションがクライアント上で変換された後、次の手順を実行します。

1. アプリケーション・コンポーネント用の.jarファイルを作成します。

2. loadjavaツールを使用して、.jarファイルをサーバーにロードします。

3. サーバーでアプリケーション用のSQLラッパーを作成します。たとえば、前述のMyExampleアプリケーションをサーバー上で実行するには、次の文を実行します。

CREATE OR REPLACE PROCEDURE sqlj_myexample AS LANGUAGE JAVA NAME `MyExample.main(java.lang.String[])';

これで、他のストアド・プロシージャと同様に、sqlj_myexampleを実行できます。

PL/SQLとの対話

Oracle JDBCドライバはすべて、Oracle SQLおよびPL/SQLとシームレスに通信し、また、SQLJとPL/SQLが相互に運用されることに注意してください。PL/SQLストアド・プロシージャを再作成せずに、SQLJを使用して開始できます。Oracle SQLJには、PL/SQLストアド・プロシージャをコールするための構文が含まれており、SQLJ文に無名PL/SQLブロックを埋め込むこともできます。

コマンドライン・インタフェースの使用

Oracle JVMへのコマンドライン・インタフェースは、JDKまたはJREのシェル・コマンドの使用方法と似ています。次のことが可能です。

- 標準の-classpath構文を使用して、ロードするクラスの検索場所を示します。

- 標準の-D構文を使用して、システム・プロパティを設定します。

このインタフェースは、文字列(VARCHAR2)引数を取り、この引数をコマンドライン入力として解析するPL/SQLファンクションです。形式が適切であれば、Oracle JVMで指定のJavaメソッドを実行します。これを実行するために、PL/SQLのパッケージDBMS_JAVAには次のファンクションが用意されています。

- runjava

- runjava_in_current_session

runjava

このファンクションは、唯一の引数としてJavaコマンドラインを取り、Oracle JVMでこれを実行します。戻り値は、正常に実行された場合はNULL、それ以外はエラー・メッセージになります。コマンドラインの形式は、JDKのシェル・コマンドと同じです。次のようになります。

[option switches] name_of_class_to_execute [arg1 arg2 ... argn]

オプションのスイッチ-classpath、-D、-Xbootclasspathおよび-jarを使用できます。このファンクションは、現在のコマンドを実行する前に、以前にJavaを使用したときからセッションに残っているJavaの状態をすべて消去するという点で、runjava_in_current_sessionファンクションと異なります。特に、クラスを初期化するときに引数-classpathおよび-Dから導出された静的変数の値が、現在のコマンドラインでのこれらのスイッチの値を確実に反映するために必要です。

FUNCTION runjava(cmdline VARCHAR2) RETURN VARCHAR2;

runjava_in_current_session

このファンクションは、現在のコマンドラインを実行する前に、以前にJavaを使用したときからセッションに残っているJavaの状態を消去しない点を除き、runjavaファンクションと同じです。

FUNCTION runjava_in_current_session(cmdline VARCHAR2) RETURN VARCHAR2;

構文

コマンドラインの構文の形式は次のとおりです。

[-options] classname [arguments...]
[-options] -jar jarfile [arguments...]

オプション

-classpath
-D
-Xbootclasspath
-Xbootclasspath/a
-Xbootclasspath/p
-cp

注意:
最初の形式では、引数を指定したclassnameで特定されるクラスのmainメソッドが実行されます。2番目の形式では、JARで識別されるJARファイルのマニフェストでMain-Class属性によって特定されるクラスのmainメソッドが実行されます。これは、JDK/JREの構文解釈法と似ています。

引数の概要

表3-1は、コマンドライン引数の一覧です。

表3-1 コマンドライン引数の概要

引数

説明

classpath

ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れて、クラス・ファイルを検索します。通常、-classpathや類似する引数の値は、標準Javaランタイムと同様にファイルシステムの場所を示します。また、この構文には拡張機能があり、データベース常駐Javaオブジェクトやバイト・セットを示す表現を使用できます。-classpathの拡張機能の詳細は、付録B「クラスパスの拡張機能およびユーザー・クラスロード・メタデータ」を参照してください。

D

既存のJavaセッションの状態がない場合、システム・プロパティの値を設定します。コマンドライン・インタフェースのデフォルトの動作、つまりrunjavaファンクションでは、新しいコマンドを実行する前に既存のJavaセッションをすべて終了します。これに対して、代替ファンクションrunjava_in_current_sessionでは、既存のセッションをそのまま残します。そのため、runjavaファンクションが使用されている場合は-Dオプションで設定された値は常に有効ですが、runjava_in_current_sessionファンクションが使用されている場合はこの値は有効ではありません。

Xbootclasspath

ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。このオプションは、ブートストラップ・クラスおよびリソースの検索パスの設定に使用します。

Xbootclasspath/a

ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの最後に付加されます。

Xbootclasspath/p

ディレクトリ、JARアーカイブおよびZIPアーカイブのコロン(:)で区切られたリスト(Windowsシステムの場合はセミコロンで区切られたリスト)を受け入れます。ブートストラップ・クラスのパスの前に付加されます。

cp

-classpathのシノニムとして機能します。

注意:
create java systemで作成されたシステム・クラスは、-Xbootclasspathオプションを使用して検出されるファイルやフォルダを使用する前に必ず使用されます。

クライアント側スタブの使用

Oracle Database 10gでは、以前はサーバー側JavaコードをコールするネイティブなJavaインタフェースとして知られていたクライアント側スタブが導入されました。これは、簡略化されたアプリケーション統合です。クライアント側および中間層のJavaアプリケーションは、PL/SQLラッパーを定義しないでデータベース内のJavaを直接コールできます。クライアント側スタブでは、サーバー側Javaクラスのリフレクション機能が使用されます。

以前のリリースでは、データベース・クライアントからJavaストアド・プロシージャおよびファンクションをコールするには、関連するPL/SQLラッパーをJava Database Connectivity(JDBC)でコールする必要がありました。各ラッパーは、SQLシグネチャおよびJava実装とともに手動で公開する必要がありました。この方法には次のデメリットがあります。

- シグネチャで許可されるJava型は、相当する型がSQLにある場合のみでした。

- Javaで発行された例外が正しく戻されません。

JPublisherの-javaオプションは、これらのデメリットを回避するための機能を提供します。関連付けられたPL/SQLラッパーに対するJDBCコールの不具合を解決するために、-javaオプションでは、static Javaメソッドを直接起動するAPIを使用します。この機能は、Webサービスにも役立ちます。

-javaオプションの機能は、-sqlオプションの機能をミラー化したもので、クライアント側Javaクラスを作成して、サーバー側のSQLオブジェクトやPL/SQLパッケージにアクセスするのではなく、クライアント側Javaスタブ・クラスを作成して、サーバー側Javaクラスにアクセスします。クライアント側のスタブ・クラスでは、サーバー側のクラスをミラー化するJPublisherコードが使用され、次の機能が含まれます。

- サーバー・クラスのpublic staticメソッドに対応するメソッド。

- 2つのコンストラクタ。1つはJDBC接続を取得するコンストラクタ、もう1つはJPublisherのデフォルトの接続コンテキスト・インスタンスを取得するコンストラクタです。

このスタブ・クラスは、実行時に、JDBC接続を使用してインスタンス化されます。スタブ・クラスのメソッドのコールは、結果としてサーバー側クラスの対応するメソッドのコールとなります。これらの公開されたメソッドで使用されるすべてのJava型は、プリミティブ型、またはシリアライズ可能型である必要があります。

図3-1に、staticサーバー側Javaメソッドを直接起動するクライアント側スタブAPIの例を示します。JPublisherでは、スタブ生成が透過的に処理されます。

図3-1 クライアント側スタブ・インタフェース

次のように、-javaオプションを使用してサーバー側Javaクラスを公開できます。

-java=className

次のAPIを使用したoracle.sqlj.checker.JdbcVersionサーバー側Javaクラスについて考えます。

public class oracle.sqlj.checker.JdbcVersion
{
...
public java.lang.String toString();
public static java.lang.String to_string();
...
}

例として、サーバーで次のメソッドをコールするとします。

public String oracle.sqlj.checker.JdbcVersion.to_string();

次のコマンドを使用して、JPublisherによりクライアント側の起動用にJdbcVersionを公開します。

% jpub -sql=HR -java=oracle.sqlj.checker.JdbcVersion:JdbcVersion Client
Enter HR password: password

このコマンドで生成されるクライアント側JavaクラスJdbcVersionClientには、次のAPIが含まれます。

public class JdbcVersionClient
{
...
public java.lang.String toString(long _handle);
public java.lang.String to_string();
...
}

すべての静的メソッドが、クライアント側のコードに含まれるインスタンス・メソッドにマップされます。サーバー側のクラスに含まれるインスタンス・メソッド(toString()など)は、追加ハンドルが含まれるメソッドにマップされます。ハンドルは、サーバーのoracle.sqlj.checker.JdbcVersionのインスタンスを表します。ハンドルは、サーバー側でのインスタンス・メソッドのコールに使用されます。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

デフォルトのサービス機能の使用

Oracle Database 11gリリース1(11.1)から、Oracle Databaseクライアントではデフォルトの新しい接続機能が提供されます。Oracle Databaseクライアントをインストールする場合、接続URLにデータベース・サーバーの詳細をすべて指定する必要はありません。特定の状況では、Oracle Database接続アダプタで、データベースがインストールされているコンピュータのホスト名のみが必要になります。

たとえば、JDBC接続URL構文では次のようになります。

jdbc:oracle:driver_type:[username/password]@[//]host_name[:port][:ORCL]

次の指定はオプションになります。

- //はオプションです。

- :portはオプションです。
Oracle Netのデフォルトのリスナー・ポート(1521)が使用されない場合のみ、ポートを指定する必要があります。

- :ORCLまたはサービス名はオプションです。
Oracle Databaseクライアントの接続アダプタは、ホストのデフォルト・サービスに接続します。ホストでは、これはlistener.oraファイルのORCLに設定されています。

基本構成を使用したデフォルト・サービスのテスト

次のコードは、デフォルト・サービスが定義されているlistener.oraファイルの基本構成を示しています。

例3-1 デフォルト・サービスが定義されたlistener.oraの基本構成

MYLISTENER = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=testserver1)(PORT=1521)))
DEFAULT_SERVICE_MYLISTENER=dbjf.app.myserver.com
SID_LIST_MYLISTENER = (SID_LIST=(SID_DESC=(SID_NAME=dbjf)
(GLOBAL_DBNAME=dbjf.app.myserver.com)(ORACLE_HOME=/test/oracle))
)

listener.oraファイルを定義した後、次のコマンドを使用してリスナーを再起動します。

lsnrctl start mylistener

これで、次のURLは、listener.oraファイルのこの構成と連携して機能します。

- jdbc:oracle:thin:@//testserver1.myserver.com.com

- jdbc:oracle:thin:@//testserver1.myserver.com:1521

- jdbc:oracle:thin:@testserver1.myserver.com

- jdbc:oracle:thin:@testserver1.myserver.com:1521

- jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)(PORT=1521)))

- jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)))

- jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver1.myserver.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=)))

注意:
デフォルト・サービスは、Oracle Database 11gリリース1(11.1)以降の機能です。Oracle Database 11gクライアントより以前のバージョンを使用してデータベースに接続する場合、SIDを指定する必要があります。

サーバー上での実行を識別する方法

サーバーとクライアントで異なる方法で実行するJavaコードを作成する場合があります。通常、このようなJavaコードの作成はお薦めしません。実際には、JDBCおよびSQLJでは、サーバーとクライアントで使用するドライバが異なる場合でも、この問題を回避する移植可能なコードを作成できます。

コードがサーバーで実行されているかどうかを確認する必要がある場合は、次のようにSystem.getProperty()メソッドを使用します。

System.getProperty ("oracle.jserver.version")

getProperty()メソッドから戻される結果は、次のとおりです。

- Oracle Databaseのリリースを表すString(サーバー上で実行中の場合)。

- null(クライアント上で実行中の場合)。

サーバー上の出力のリダイレクト

Oracle JVMの出力先をさらに広範囲にわたって制御するために、SQL文にJava出力を渡すことができます。PL/SQLのパッケージDBMS_JAVAは次の新しいファンクションを追加することで拡張され、これにより、以前はDBMS_JAVA.SET_OUTPUTプロシージャでのみ使用可能であった機能が拡張されています。

- set_output_to_sql

- remove_output_to_sql

- enable_output_to_sql

- disable_output_to_sql

- query_output_to_sql

set_output_to_sql

set_output_to_sqlは、デフォルトのSystem.outおよびSystem.errへの出力ストリームが発生すると、SQL文の実行命令で構成される指定の出力仕様を定義します。この仕様は、現在のセッションの期間内、またはremove_output_to_sqlファンクションがそのIDでコールされるまで定義されます。Java出力がある場合、仕様で規定されたSQLアクションが実行されます。これを停止するにはdisable_output_to_sqlファンクションをコールし、開始するにはenable_output_to_sqlファンクションをコールします。このファンクションの戻り値は、正常に実行された場合はNULL、それ以外はエラー・メッセージになります。

FUNCTION set_output_to_sql (id VARCHAR2,
stmt VARCHAR2,
bindings VARCHAR2,
no_newline_stmt VARCHAR2 default null,
no_newline_bindings VARCHAR2 default null,
newline_only_stmt VARCHAR2 default null,
newline_only_bindings VARCHAR2 default null,
maximum_line_segment_length NUMBER default 0,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1,
include_newlines NUMBER default 0,
eager NUMBER default 0) return VARCHAR2;

表3-2に、set_output_to_sqlファンクションが取る引数を示します。

表3-2 set_output_to_sqlの引数の概要

引数

説明

id

仕様の名前。同じセッションで複数の仕様を使用できますが、それぞれに個別のIDが必要です。このIDを使用して、remove_output_to_sql、enable_output_to_sql、disable_output_to_sqlおよびquery_output_to_sqlの各ファンクションで仕様を識別します。

stmt

Java出力が発生した場合に実行するデフォルトのSQL文。

bindings

セットID、TEXT、LENGTH、LINENO、SEGNO、NLおよびERROUTからのトークンを含む文字列。この文字列は、SQL文stmtがバインドされる方法を定義します。bindings文字列でのトークンの位置は、SQL文でのバインドの位置に相当します。トークンの意味は次のとおりです。

- IDは仕様のIDです。VARCHAR2でバインドされます。

- TEXTは出力されるテキストです。VARCHAR2でバインドされます。

- LENGTHはテキストの長さです。NUMBERでバインドされます。

- LINENOは、セッション出力の開始以降の行番号です。NUMBERでバインドされます。

- SEGNOは、複数の要素で出力される行内のセグメント番号です。NUMBERでバインドされます。

- NLは、テキストが改行で終わるとみなされるかどうかを示すブール値です。NUMBERでバインドされます。引数include_newlinesの値に応じて、改行が実際にテキストに含まれる場合と含まれない場合があります。

- ERROUTは、出力がSystem.outまたはSystem.errのどちらからであるかを示すブール値です。NUMBERでバインドされます。System.outからの出力の場合、値は0です。

no_newline_stmt

出力が改行で終わらない場合に実行するオプションの代替SQL文。

no_newline_bindings

前述のbindings引数と同じ構文を使用する文字列。no_newline_stmtがバインドされる方法を示します。

newline_only_stmt

出力が1つの改行の場合に実行するオプションの代替SQL文。

newline_only_bindings

前述のbindings引数と同じ構文を使用する文字列。newline_only_stmtがバインドされる方法を示します。

maximum_line_segment_length

指定されたSQL文の実行でバインドされる最大文字数。出力シーケンスが長い場合、識別可能なSEGNO値によって個々のコールに分けられます。値0はno maximumを表します。

allow_replace

同じIDの仕様が以前に定義されている場合の動作を制御します。値1は、古い仕様を置き換えます。0は、古い仕様を変更せずにエラー・メッセージを戻します。

from_stdout

System.outからの出力によって、仕様で規定されたSQL文が実行されるかどうかを制御します。値0は、System.outからの出力であった場合、それ以外で仕様が有効であったとしても、文が実行されないことを示します。

from_stderr

System.errからの出力によって、仕様で規定されたSQL文が実行されるかどうかを制御します。値0は、System.errからの出力であった場合、それ以外で仕様が有効であったとしても、文が実行されないことを示します。

include_newlines

改行文字がテキストにバインドされる場合、それらの文字が出力に残るかどうかを制御します。値0は改行が含まれないことを示します。ただし、改行が存在するかどうかは、NLバインディングやno_newline_stmtが使用されていることからもわかります。

eager

改行で終了しない出力により、改行を受け取るたびにSQL文を実行するかどうかを制御するか、または、改行を受け取るまでこのような出力を蓄積します。値0は、終了しない出力が蓄積されることを示します。

remove_output_to_sql

remove_output_to_sqlは、set_output_to_sqlで作成された仕様を削除します。このような仕様がない場合は、エラー・メッセージが戻されます。

FUNCTION remove_output_to_sql (id VARCHAR2) return VARCHAR2;

enable_output_to_sql

enable_output_to_sqlは、set_output_to_sqlで作成された後、disable_output_to_sqlで無効化された仕様を再度有効にします。このような仕様がない場合は、エラー・メッセージが戻されます。現在、仕様が無効ではない場合、変更はありません。

FUNCTION enable_output_to_sql (id VARCHAR2) return VARCHAR2;

disable_output_to_sql

disable_output_to_sqlは、set_output_to_sqlで作成された仕様を無効にします。仕様を有効にするには、enable_output_to_sqlをコールします。無効になっている間、仕様で規定されたSQL文は実行されません。このような仕様がない場合は、エラー・メッセージが戻されます。仕様がすでに無効の場合、変更はありません。

FUNCTION disable_output_to_sql (id VARCHAR2) return VARCHAR2;

query_output_to_sql

query_output_to_sqlは、set_output_to_sqlで作成された仕様を説明するメッセージを戻します。このような仕様がない場合は、エラー・メッセージが戻されます。このファンクションにnullを渡すと、既存のすべての仕様が表示されます。

FUNCTION query_output_to_sql (id VARCHAR2) return VARCHAR2;

Oracle JVMからの出力先を制御するには、自律型JavaセッションにJava出力を渡す方法もあります。これは、ディスク・ファイル、ソケットおよびURLなどの各種ターゲットに出力を伝播する一般的なメカニズムを提供します。ただし、出力を処理するJavaセッションはメイン・セッションとは論理的に異なるため、セッション間でその他の不要な相互作用はない点に注意する必要があります。これを実行するために、PL/SQLのパッケージDBMS_JAVAには次のファンクションが用意されています。

- set_output_to_java

- remove_output_to_java

- enable_output_to_java

- disable_output_to_java

- query_output_to_java

- set_output_to_file

- remove_output_to_file

- enable_output_to_file

- disable_output_to_file

- query_output_to_file

set_output_to_java

set_output_to_javaは、デフォルトのSystem.outおよびSystem.errへの出力ストリームが発生すると、Javaメソッドを実行する命令を与える指定の出力仕様を定義します。仕様で規定されたJavaメソッドは、セッションの残りの部分とは別のJavaセッションの状態を持つ別のVMコンテキストで実行されます。

FUNCTION set_output_to_java (id VARCHAR2,
class_name VARCHAR2,
class_schema VARCHAR2,
method VARCHAR2,
bindings VARCHAR2,
no_newline_method VARCHAR2 default null,
no_newline_bindings VARCHAR2 default null,
newline_only_method VARCHAR2 default null,
newline_only_bindings VARCHAR2 default null,
maximum_line_segment_length NUMBER default 0,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1,
include_newlines NUMBER default 0,
eager NUMBER default 0,
initialization_statement VARCHAR2 default null,
finalization_statement VARCHAR2 default null)return VARCHAR2;

表3-3に、set_output_to_javaメソッドが取る引数を示します。

表3-3 set_output_to_javaの引数の概要

引数

説明

class_name

1つ以上のメソッドを定義するクラスの名前。

class_schema

クラスが定義されるスキーマ。NULL値は、現行スキーマまたはPUBLICでクラスが定義されることを示します。

method

メソッドの名前。

bindings

メソッドの引数がバインドされる方法を定義する文字列。これは、set_output_to_sqlと同じ構文を使用するトークンの文字列です。文字列内のトークンの位置によって、そのトークンが表す引数の位置が決まります。java.lang.String型であるIDまたはTEXTのトークンに相当する引数を除き、すべての引数はINT型です。

no_newline_method

出力が改行で終わらない場合に実行するオプションの代替メソッド。

newline_only_method

出力が1つの改行の場合に実行するオプションの代替メソッド。

initialization_statement

出力を受け取るメソッドを最初に実行する前に、Javaセッションごとに1回実行されるオプションのSQL文。この文は、出力メソッドが実行されるのと同じJava VMコンテキストで実行されます。通常、このような文は、出力を受け取るメソッドが予定どおりに機能するように、別のVMコンテキストで条件を初期化するJavaストアド・プロシージャを実行する際に使用します。たとえば、このようなプロシージャは、出力メソッドによって書き込まれるストリームを開きます。

finalization_statement

出力仕様が削除される直前、またはセッションが終了するときに1回実行されるオプションのSQL文。initialization_statementと同様、出力を受け取るメソッドと同じJVMコンテキストで実行されます。初期化メソッドを実行した場合のみ、または初期化メソッドがない場合に実行されます。

remove_output_to_java

remove_output_to_javaは、set_output_to_javaで作成された仕様を削除します。このような仕様がない場合、エラー・メッセージが戻されます。

FUNCTION remove_output_to_java (id VARCHAR2) return VARCHAR2;

enable_output_to_java

enable_output_to_javaは、set_output_to_javaで作成された後、disable_output_to_javaで無効化された仕様を再度有効にします。このような仕様がない場合は、エラー・メッセージが戻されます。現在、仕様が無効ではない場合、変更はありません。

FUNCTION enable_output_to_java (id VARCHAR2) return VARCHAR2;

disable_output_to_java

disable_output_to_javaは、set_output_to_javaで作成された仕様を無効にします。仕様は、enable_output_to_javaで再度有効にできます。無効になっている間、仕様で規定されたSQL文は実行されません。このような仕様がない場合は、エラー・メッセージが戻されます。仕様がすでに無効の場合、変更はありません。

FUNCTION disable_output_to_java (id VARCHAR2) return VARCHAR2;

query_output_to_java

query_output_to_javaは、set_output_to_javaで作成された仕様を説明するメッセージを戻します。このような仕様がない場合は、エラー・メッセージが戻されます。このファンクションにnullを渡すと、既存のすべての仕様が表示されます。

FUNCTION query_output_to_java (id VARCHAR2) return VARCHAR2;

set_output_to_file

set_output_to_fileは、デフォルトのSystem.outおよびSystem.errに送信された出力ストリームを捕捉し、これを特定のファイルに追加する命令で構成された指定の出力仕様を定義します。これを実装するには、特殊なset_output_to_javaを使用します。引数file_pathは、出力の追加先のファイルのパスを指定します。引数allow_replace、from_stdoutおよびfrom_stderrは、set_output_to_sqlの同じ名前の引数と類似しています。

FUNCTION set_output_to_file (id VARCHAR2,
file_path VARCHAR2,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1) return VARCHAR2;

remove_output_to_file

このファンクションは、remove_output_to_javaと似ています。

FUNCTION remove_output_to_file (id VARCHAR2) return VARCHAR2;

enable_output_to_file

このファンクションは、enable_output_to_javaと似ています。

FUNCTION enable_output_to_file (id VARCHAR2) return VARCHAR2;

disable_output_to_file

このファンクションは、disable_output_to_javaと似ています。

FUNCTION disable_output_to_file (id VARCHAR2) return VARCHAR2;

query_output_to_file

このファンクションは、query_output_to_javaと似ています。

FUNCTION query_output_to_file (id VARCHAR2) return VARCHAR2;

次のDBMS_JAVAファンクションは、.trcファイルにJava出力が表示されるかどうかを制御します。

- PROCEDURE enable_output_to_trc;

- PROCEDURE disable_output_to_trc;

- FUNCTION query_output_to_trc return VARCHAR2;

注意:
11gリリース1 (11.1)以前は、.trcファイルに表示されるJava出力は変更できませんでした。

SQL*Plusテキスト・バッファへの出力のリダイレクト

以前のリリースと同様、DBMS_JAVAパッケージのプロシージャSET_OUTPUTを使用して、SQL*Plusテキスト・バッファに出力をリダイレクトできます。

SQL> SET SERVEROUTPUT ON
SQL> CALL dbms_java.set_output(2000);

最小(デフォルト)バッファ・サイズは2,000バイトで、最大サイズは1,000,000バイトです。次の例では、バッファ・サイズを5,000バイトに増やしています。

SQL> SET SERVEROUTPUT ON SIZE 5000
SQL> CALL dbms_java.set_output(5000);

出力は、コール終了時に表示されます。

データベースでのJavaの直接コール

Oracle Database 10gより前のリリースでは、データベース・クライアントからJavaストアド・プロシージャおよびファンクションをコールするには、関連するPL/SQLラッパーをJDBCでコールする必要がありました。各ラッパーは、SQLシグネチャおよびJava実装とともに手動で公開する必要がありました。この方法には次のデメリットがあります。

- Javaメソッド用にSQLシグネチャを公開するために、別の手順が必要でした。

- シグネチャで許可されるJava型は、相当する型がSQLにある型のみでした。

- Javaで発行された例外が正しく戻されませんでした。

- 1回のデータベース・ラウンドトリップごとに実行できるメソッドの起動が1回のみでした。

これらの問題を解決するために、Oracle Database 11g以降では、static Javaストアド・プロシージャおよびファンクションの直接コール用に、簡易APIが実装されています。この新機能は一般的なアプリケーションにも役立ちますが、特にWebサービスに役立ちます。

簡易APIのクラスはoracle.jpub.reflectパッケージに格納されています。このパッケージをクライアント側のコードにインポートします。

次に、API用のJavaインタフェースを示します。

public class Client
{
public static String getSignature(Class[]);
public static Object invoke(Connection, String, String, String, Object[]);
public static Object invoke(Connection, String, String, Class[], Object[]);
}

例として、サーバーで次のメソッドをコールするとします。

public String oracle.sqlj.checker.JdbcVersion.to_string();

このメソッドは次のようにコールできます。

Connection conn = ...;
String serverSqljVersion = (String)
Client.invoke(conn, "oracle.sqlj.checker.JdbcVersion","to_string", new Class[]{}, new Object[]{});

Class[]配列はメソッドのパラメータ・タイプ用で、Object[]配列はパラメータの値用です。この場合、to_stringにはパラメータがないため、配列は空です。

次の点に注意してください。

- 任意のシリアル化可能な型(例: int[]およびString[])を引数として渡すことができます。

- 最適化として、パラメータ値をStringとして表すことができます。

String sig = oracle.jpub.reflect.Client.getSignature(new Class[]{});
...
Client.invoke(conn, "oracle.sqlj.checker.JdbcVersion", "to_string",sig, new Object[]{});

- このAPIのセマンティクスは、PL/SQLラッパーを使用してストアド・プロシージャまたはファンクションをコールする場合のセマンティクスと次の点で異なります。

- 引数をOUTまたはIN OUTに設定することはできません。戻り値はすべてファンクションの結果の一部であることが必要です。

- 例外が正しく戻されます。

- メソッドの起動で実行者権限が使用されます。定義者権限を取得するようにはチューニングされていません。

4 Javaのインストールと構成

この章では、Oracle JVMをインストールおよび構成する方法について説明します。また、Javaクライアントを使用可能にする方法についても説明します。この章の構成は、次のとおりです。

- Java対応のデータベースの初期化

- Oracle JVMの構成

- DBMS_JAVAパッケージの使用方法

- Javaクライアントを使用可能にする方法

- Javaセッションの状態に使用する2層の期間

- システム・プロパティの設定

Java対応のデータベースの初期化

Oracle JVMオプションを指定してOracle Databaseをインストールすると、データベースはJava対応になります。つまり、Javaストアド・プロシージャ、Java Database Connectivity(JDBC)およびSQLJが実行可能な状態になります。

この項の内容は、次のとおりです。

- Oracle Databaseのテンプレートを使用した構成

- Oracle JVMを組み込むための既存のOracle Databaseの変更

Oracle Databaseのテンプレートを使用した構成

Oracle JVMオプションをデータベース・テンプレート内に構成します。Javaのインストールには、この方法をお薦めします。

Database Configuration Assistantを使用すると、各データベース・インスタンスのインストールに含める内容を定義するためのデータベース・テンプレートを作成できます。Javaプラットフォームをデータベース内にインストールする場合は、Oracle JVMオプションを選択してください。

Oracle JVMを組み込むための既存のOracle Databaseの変更

Oracle JVMを組み込まずにOracle Databaseをすでにインストールしている場合は、Oracle Database 12cリリース1 (12.1)のDatabase Configuration Assistantの変更モードを使用してデータベースにJavaを追加できます。変更モードでは、既存のOracle Databaseインスタンス上にインストールする機能(Oracle JVMなど)を選択できます。

Oracle JVMの構成

Oracle JVMをOracle Databaseの標準インストールの一部としてインストールする前に、Oracle JVMの構成要件がすべて満たされていることを確認する必要があります。Oracle Database内のJavaクラスの主な構成には、次の構成要件が含まれます。

- Javaメモリー要件
JAVA_POOL_SIZEに最低50MB、SHARED_POOL_SIZEに最低96MB必要です。

関連項目:
「Javaのメモリー使用量」

- データベース・プロセス
データベース・サーバーに専用サーバー・プロセスまたは共有サーバー・プロセスのどちらを使用するかを決定する必要があります。

DBMS_JAVAパッケージの使用方法

Oracle JVMをインストールすると、PL/SQLのDBMS_JAVAパッケージが作成されます。DBMS_JAVAパッケージ・ファンクションは、データベース・サーバーとデータベース・クライアントのどちらでも使用できます。対応するJavaクラスDbmsJavaで、Javaからデータベースの機能にアクセスするためのメソッドが提供されます。

関連項目:
付録A「DBMS_JAVAパッケージ」

Javaクライアントを使用可能にする方法

クライアントとサーバー間でJavaを実行するには、次の手順を実行する必要があります。

1. クライアントへのJava SEのインストール

2. 環境変数の設定

3. サンプルを使用したインストールのテスト

クライアントへのJava SEのインストール

クライアントにはJava Development Kit(JDK)1.6以上が必要です。使用しているJDKのバージョンを確認するには、コマンドラインで次のコマンドを実行します。

$ which java
/usr/local/jdk1.6.0_26/bin/java

$ which javac
/usr/local/jdk1.6.0_26/bin/javac

$ java -version
java version "1.6.0_26"

環境変数の設定

クライアントにJDKをインストールした後に、次の環境変数にディレクトリ・パスを追加します。

- $JAVA_HOME
この変数は、インストールしたJDKベースの最上位ディレクトリに設定する必要があります。

- $PATH
この変数には、$JAVA_HOME/binを組み込む必要があります。

- $LD_LIBRARY_PATH
この変数には、$JAVA_HOME/libを組み込む必要があります。

Java 2クライアントに必要なJARファイル

Javaクライアントでサーバーと正常に通信できるようにするには、CLASSPATHに次のファイルを組み込みます。

注意:
CLASSPATH要件の詳細は、異なるプラットフォームで実行されるOracle JVMごとに異なる可能性があります。Oracle JVMユーティリティのスクリプトに定義されたすべてのCLASSPATHの要素が存在する必要があります。

- JDK 1.5.2の場合は、$JAVA_HOME/lib/dt.jarを組み込みます。

- JRE 1.5.2の場合は、$JAVA_HOME/lib/rt.jarを組み込みます。

- JDBCと対話するには、$ORACLE_HOME/jdbc/lib/ojdbc5.jarを組み込みます。

- SSLを使用するクライアントの場合は、$ORACLE_HOME/jlib/jssl-1_2.jarおよび$ORACLE_HOME/jlib/javax-ssl-1_2.jarを組み込みます。

- Java Transaction API(JTA)の機能を使用するクライアントの場合は、$ORACLE_HOME/jlib/jta.jarを組み込みます。

- Java Naming and Directory Interface(JNDI)の機能を使用するクライアントの場合は、$ORACLE_HOME/jlib/jndi.jarを組み込みます。

- ネイティブ・コンパイル用のAcceleratorを使用している場合は、$JAVA_HOME/lib/tools.jarを組み込みます。

SQLJを使用するクライアント用に組み込むJARファイル

SQLJ用に$ORACLE_HOME/sqlj/lib/translator.zipファイルを組み込む必要があります。

このファイル以外に、適切なruntimeX.zipファイルを次のように追加します。

- 現行リリースのJDBCを使用しているJavaクライアントの場合は、$ORACLE_HOME/sqlj/lib/runtime12.zipを組み込みます。

- 現行リリースのJDBCを使用しているJava2 Platform, Enterprise Edition(J2EE)クライアントの場合は、$ORACLE_HOME/sqlj/lib/runtime12ee.zipを組み込みます。

- 8.1.7バージョンより前のJDBCを使用しているJDKクライアントの場合は、$ORACLE_HOME/sqlj/lib/runtime.zipを組み込みます。

クライアントでのサーバー・アプリケーションの開発

クライアントでサーバー・アプリケーションを開発およびコンパイルし、サーバーにロードされている同じJavaアーカイブ(JAR)ファイルを使用する場合は、CLASSPATHに$ORACLE_HOME/lib/aurora.zipを組み込みます。これは、Javaクライアントの実行には必要ありません。

サンプルを使用したインストールのテスト

Oracle JVMオプションを指定してOracle Databaseをインストールすると、$ORACLE_HOME/javavm/demoディレクトリにサンプル・セットもインストールされ、使用できます。これらのサンプルはインストールのテストとしてコンパイルおよび実行できます。

サンプルがコンパイルまたは実行されない場合は、環境が正しく設定されていない可能性があります。同様に、これらのサンプルがコンパイルおよび実行されても、ユーザーが作成したコードがコンパイルおよび実行されない場合は、作成環境またはコードに問題があります。

注意:
インストールを検証するときは、提供されているMakeファイルを使用してこれらの例を実行することが重要です。

Visual Cafe、JDeveloperまたはVisualAgeなどのより複雑な作成環境を使用する前に、サンプルが動作することを確認してください。

Javaセッションの状態に使用する2層の期間

11gリリース1 (11.1)以前では、Javaセッションの状態は単一層で、ここには、Javaの実行に関連するすべての値(システム・プロパティの値や静的変数の値など)、およびセッション中にロードされたクラスのセットなどが含まれていました。この状態の期間は、RDBMSセッションで最初にJavaメソッドを起動すると開始し、java.lang.System.exitまたは類似するOracleRuntimeメソッドのコール、捕捉されない例外、致命的エラーまたはRDBMSセッションの終了のいずれかによってJVMが終了するまで続いていました。この場合、Javaコードの変更が必要であり、さらにRDBMSコールの終了前にセッションを完全に終了することができませんでした。そのため、同じコール内で新しいJavaセッションを起動できませんでした。

11gリリース1 (11.1)以降では、Javaセッションの状態が2層に分けられています。一方の層の期間の方が長く、この中にもう一方の層の期間が含まれます。短い層の期間は以前と同じで、つまり、Javaメソッドを起動すると開始し、JVMが終了すると終了します。長い層の期間は、RDBMSセッションで最初にJavaメソッドを起動すると開始します。このセッションは、RDBMSセッションが終了するか、またはファンクションdbms_java.endsession_and_related_stateのコールによってセッションを明示的に終了するまで続きます。Javaセッションの2種類の期間で構成される、次の2つのPL/SQLファンクションをDBMS_JAVAパッケージに追加することで、この問題に対応しています。

- FUNCTION endsession RETURN VARCHAR2;
このファンクションは、以前にJavaを実行したときからRDBMS現行セッションに残っているJavaセッションの状態をすべて消去します。戻り値は、実行されるアクションを示すメッセージです。

- FUNCTION endsession_and_related_state RETURN VARCHAR2;
このファンクションは、以前にJavaを実行したときからRDBMS現行セッションに残っているJavaセッションの状態と、Javaの実行に関連するサポート・データ(プロパティの設定や出力仕様など)をすべて消去します。戻り値は、実行されるアクションを示すメッセージです。

Javaの実行に関連するほとんどの値は、引き続き短い層にあります。JVMを複数起動する場合に役立つ値は、長い層に移動されました。たとえば、dbms_java.set_propertyで設定するシステム・プロパティの値や出力リダイレクトの仕様などです。

関連項目:
「システム・プロパティの設定」および「サーバー上の出力のリダイレクト」。

システム・プロパティの設定

RDBMSセッション内では、JavaセッションをRDBMSセッションで起動する場合、システム・プロパティに追加される値のセットを管理できます。この値のセットは、Javaセッションの状態の長い層の期間で有効な状態が維持され、これは、通常、RDBMSセッションと同じ期間です。

関連項目:
「Javaセッションの状態に使用する2層の期間」

DBMS_JAVAパッケージには、内部のRDBMSセッション期間表でキーと値のペアを設定、取得、削除および表示するためのPL/SQLファンクションのセットがあります。ここでは、ペアのどちらの要素も文字列(VARCHAR2)であり、指定のキーに対して最大1つのペアがあります。ファンクションは次のとおりです。タスクの機能は次のとおりです。

- set_property

- get_property

- remove_property

- show_property

set_property

このファンクションでは、Javaセッションが初期化されると、RDBMSの現行セッションの期間に使用されるシステム・プロパティの値を設定します。最初の引数はプロパティの名前、2番目の引数はプロパティに設定される値です。set_propertyの戻り値は、エラーがないかぎりNULLになります。たとえば、規定のプロパティの値を設定しようとすると、エラー・メッセージが戻されます。

FUNCTION set_property(name VARCHAR2, value VARCHAR2) RETURN VARCHAR2;

get_property

このファンクションは、set_propertyで以前に設定された値を戻します。値がない場合はNULLを戻します。

FUNCTION get_property(name VARCHAR2) RETURN VARCHAR2;

remove_property

このファンクションは、set_propertyで以前に設定された値を削除します。エラーが発生しなければ、戻り値はNULLになり、エラーが発生した場合、エラー・メッセージが戻されます。

FUNCTION remove_property(name VARCHAR2) RETURN VARCHAR2;

show_property

このファンクションは、nameがNULLの場合、入力名または設定されたすべてのプロパティのバインディングについて、name = valueという形式のメッセージを表示します。このファンクションの戻り値は、正常に実行された場合はNULL、それ以外はエラー・メッセージになります。出力は、現在のJava出力の指定先に表示されます。

FUNCTION show_property(name VARCHAR2) RETURN VARCHAR2;

Javaセッションを初期化する前に、Oracle JVMですでに管理されているデフォルトのシステム・プロパティの値セットにこの表の値が追加されます。コマンドライン・インタフェースを使用してJavaメソッドを実行する場合、-Dオプション(指定する場合)で決定した値は、表の値セットをオーバーライドします。Javaセッションを終了するとすぐに、-Dオプションで設定した値は使用されなくなり、キーは表にある元の値に設定されます。

5 Javaストアド・プロシージャの開発

Oracle JVMは、次世代の企業規模のアプリケーションを低コストで作成するために必要な機能をすべて備えています。最も重要な機能は、ストアド・プロシージャのサポートです。ストアド・プロシージャを使用すると、ビジネス・ロジックをサーバー・レベルで実装できるため、アプリケーションのパフォーマンス、スケーラビリティおよびセキュリティが向上します。

この章の内容は、次のとおりです。

- ストアド・プロシージャとランタイム・コンテキスト

- ストアド・プロシージャの利点

- Javaストアド・プロシージャの手順

- Javaストアド・プロシージャのデバッグ

ストアド・プロシージャとランタイム・コンテキスト

ストアド・プロシージャは、SQLに対して公開され、一般的に使用できるようにデータベースに格納されるJavaメソッドです。Javaメソッドを公開するには、Javaメソッド名、パラメータ・タイプおよび戻り型を、対応するSQLにマップするコール仕様を記述します。

別の実行レイヤーが追加されるラッパーとは異なり、コール仕様では、Javaメソッドの存在が公開されます。したがって、コール仕様を使用してメソッドをコールすると、ランタイム・システムによって、最小限のオーバーヘッドでコールがディスパッチされます。

ストアド・プロシージャは、クライアント・アプリケーションからコールされると、引数を受け入れ、Javaクラスを参照し、Javaの結果値を戻すことができます。

図5-1では、様々なアプリケーションからコールされているストアド・プロシージャを示しています。

図5-1 ストアド・プロシージャのコール

グラフィカル・ユーザー・インタフェース(GUI)のメソッドを除いて、Oracle JVMは、すべてのJavaメソッドをストアド・プロシージャとして実行できます。ランタイム・コンテキストには、次のものが含まれます。

- ファンクションおよびプロシージャ

- データベース・トリガー

- オブジェクト・リレーショナル・メソッド

ファンクションおよびプロシージャ

ファンクションとプロシージャは、一連の文をカプセル化した名前付きのブロックです。これらは、モジュール化されたメンテナンスが容易なアプリケーションを作成するために使用できる構成単位となります。

一般的に、プロシージャは処理の実行に使用し、ファンクションは値の計算に使用します。したがって、戻り値がvoidのJavaメソッドの場合は、プロシージャのコール仕様を使用し、値を戻すメソッドの場合は、ファンクションのコール仕様を使用します。

トップレベルおよびパッケージレベルのPL/SQLファンクションおよびプロシージャのみをコール仕様として使用できます。SQLのCREATE FUNCTION、CREATE PROCEDUREまたはCREATE PACKAGE文を使用してファンクションとプロシージャを定義すると、これらはデータベースに格納され、一般的に使用可能になります。

ファンクションおよびプロシージャとして公開されたJavaメソッドは、明示的に起動する必要があります。これらのメソッドには引数を指定でき、次の文やプログラムからコール可能です。

- SQLデータ操作言語(DML)文

- SQLのCALL文

- PL/SQLのブロック、サブプログラムおよびパッケージ

データベース・トリガー

データベース・トリガーは、特定の表またはビューに関連付けられたストアド・プロシージャです。指定されたDML操作で表またはビューが変更されるたびに、Oracle Databaseによってトリガーが自動的にコールされます。

トリガーは次の3つの部分で構成されています。

- トリガー・イベント(通常はDML操作)

- オプションのトリガー制約

- トリガー・アクション

イベントが発生すると、トリガーがコールされます。トリガーのCALL文によって、Javaメソッドがそのメソッドのコール仕様を使用してコールされてアクションが実行されます。

データベース・トリガーは、複雑なビジネス・ルールの実施、列値の自動取得、無効なトランザクションの防止、イベントの透過的な記録、トランザクションの監査および統計情報の収集に使用されます。

オブジェクト・リレーショナル・メソッド

SQLオブジェクト型は、属性と呼ばれる一連の変数と、メソッドと呼ばれる一連の操作をカプセル化したユーザー定義のコンポジット・データ型で、Javaで作成できます。一連の属性で構成されたデータ構造は、publicです。ただし、プログラミングの慣例として、アプリケーションでこれらの属性が直接操作されず、提供される一連のメソッドが使用されることを確認する必要があります。

SQLオブジェクト型として、実在のオブジェクトに対応する抽象テンプレートを作成できます。テンプレートでは、オブジェクトがアプリケーション環境で必要とする属性とメソッドのみを指定します。実行時(データ構造に値を割り当てるとき)に、オブジェクト型のインスタンスを作成します。インスタンスは必要な数だけ作成できます。

通常、オブジェクト型は、発注書などのビジネス・エンティティに対応します。項目の変数値を格納するには、オブジェクト型ではVARRAYまたはネストした表(あるいはその両方)を使用できます。

たとえば、発注書のオブジェクト型に明細項目の変数値を格納できます。

ストアド・プロシージャの利点

ストアド・プロシージャにはいくつかの利点があります。この項では次の利点について説明します。

- パフォーマンス

- 生産性と使いやすさ

- スケーラビリティ

- メンテナンス性

- 相互運用性

- レプリケーション

- セキュリティ

パフォーマンス

ストアド・プロシージャは、一度コンパイルされて実行可能な形式で格納されています。そのため、プロシージャ・コールが迅速かつ効率的に処理されます。実行可能コードは自動的にキャッシュされ、ユーザー間で共有されます。この結果、メモリー要件や起動時のオーバーヘッドが低減します。

SQL文をグループ化することによって、ストアド・プロシージャではそれらを1回のコールで処理できます。この結果、ネットワークの通信量が減少し、ラウンドトリップの応答時間が短縮されます。

また、ストアド・プロシージャを使用すると、サーバーのコンピューティング資源を利用できます。たとえば、計算専用プロシージャをクライアントからサーバーに移動すると、サーバーでより高速に実行できます。ストアド・ファンクションにより、サーバー内でアプリケーション・ロジックが実行されるため、パフォーマンスが向上します。

生産性と使いやすさ

共通のストアド・プロシージャのセットの周囲にアプリケーションを設計することによって、冗長なコーディングを回避し、生産性を向上させることができます。さらに、ストアド・プロシージャを使用するとデータベースの機能を拡張できます。

ストアド・プロシージャの作成には、希望に応じてJava統合開発環境(IDE)を使用できます。これらのストアド・プロシージャは、Java Database Connectivity(JDBC)などの標準Javaインタフェース、またはSQLJ、Oracle Call Interface(OCI)、Pro*C/C++およびJDeveloperなどのプログラム・インタフェースや開発ツールによりコールできます。

このようなストアド・プロシージャへの広範囲にわたるアクセス方法によって、アプリケーション間でビジネス・ロジックを共有できます。たとえば、ビジネス・ルールを実装するストアド・プロシージャは、様々なクライアント・サイド・アプリケーションからコールできるため、そのすべてのアプリケーションがビジネス・ルールを共有できます。また、サーバーのJava機能を利用する一方で、任意のプログラム・インタフェース用のアプリケーションを引き続き作成できます。

スケーラビリティ

データベースのJavaは、Oracleデータベースのスケーラブルなセッション・モデルを継承します。ストアド・プロシージャでは、サーバー上のアプリケーション処理を独立することによってスケーラビリティが向上します。また、ストアド・プロシージャの依存性自動追跡機能は、スケーラブルなアプリケーションの開発に役立ちます。

メンテナンス性

妥当性チェックが実施されているストアド・プロシージャは、どのアプリケーションでも使用できます。ストアド・プロシージャの定義が変更された場合、影響を受けるのはそのプロシージャのみで、プロシージャをコールするアプリケーションには影響しません。このため、メンテナンスおよび拡張が容易になります。また、1つのプロシージャをサーバー上でメンテナンスする方が、様々なクライアント・コンピュータ上のコピーをメンテナンスするより簡単です。

相互運用性

Oracle Databaseで、JavaはJava言語仕様(JLS)に完全に準拠し、汎用のオブジェクト指向プログラミング言語の利点をすべて提供します。また、PL/SQLと同様に、JavaではOracleデータへのフル・アクセスが提供されています。そのため、PL/SQLで作成されるプロシージャはすべてJavaで作成できます。

Javaストアド・プロシージャはPL/SQLストアド・プロシージャによって補完されます。通常、プロシージャ型の拡張機能を必要とするSQLプログラマはPL/SQLを使用することが多く、Oracleデータに簡単にアクセスする必要があるJavaプログラマはJavaをよく使用します。

Oracle Databaseを使用すると、JavaとPL/SQL間の高度な相互運用性が実現します。Javaアプリケーションは埋込み型のJDBCドライバを使用してPL/SQLストアド・プロシージャをコールできます。一方、PL/SQLアプリケーションはJavaストアド・プロシージャを直接コールできます。

レプリケーション

Oracle Advanced Replicationを使用すると、ストアド・プロシージャをOracle Databaseのあるインスタンスから別のインスタンスにレプリケートできます。この機能により、ストアド・プロシージャを使用して基本的なビジネス・ルール・セットを実装できます。ストアド・プロシージャは、一度作成すると、レプリケートして、企業内の作業グループや支店に配布できます。この方法で、個々のサーバーではなく中央のサーバーでポリシーを改訂できます。

セキュリティ

セキュリティの範囲は広く、次のものが含まれます。

- 接続に関するネットワーク・セキュリティ

- オペレーティング・システム・リソースまたはJVM定義クラスやユーザー定義クラスのアクセス制御および実行制御

- 外部ソースからインポートされたJARファイルのバイトコード検証。

Oracle Databaseでは、すべてのクラスがセキュアなデータベースにロードされるため、アントラステッドな状態になります。ユーザーがクラスおよびオペレーティング・システム・リソースにアクセスするには、適切なパーミッションが必要です。同様に、すべてのストアド・プロシージャは他のユーザーから保護されています。ストアド・プロシージャにアクセスする必要があるユーザーに、EXECUTEデータベース権限を付与できます。

また、ユーザーに対しては、定義者権限で実行されるストアド・プロシージャのみからOracleデータの操作を許可することによって、Oracleデータへのアクセスを制限できます。たとえば、データベースの表を更新するプロシージャへのアクセスは許可しても、その表自体へのアクセスは拒否することもできます。

関連項目:
第10章「Oracle Database Javaアプリケーションのセキュリティ」

Javaストアド・プロシージャの手順

Javaストアド・プロシージャは、PL/SQLストアド・プロシージャと同じ方法で実行できます。Javaストアド・プロシージャは、トリガーまたはSQL DMLコールの結果としてコールされることが一般的なため、通常はデータベース操作の結果として実行されます。Javaストアド・プロシージャをコールするには、コール仕様を使用して公開する必要があります。

Javaストアド・プロシージャをコールする前に、それらをOracle Databaseインスタンスにロードし、SQLに対して公開する必要があります。ロードと公開は別のタスクです。多くのJavaクラスは、他のJavaクラスからのみ参照されるため公開されることはありません。

Javaストアド・プロシージャを自動的にロードするには、loadjavaツールを使用します。これは、Javaのソース、クラスおよびリソース・ファイルを、システムによって生成されたデータベース表にロードし、次にSQLのCREATE JAVA {SOURCE | CLASS | RESOURCE}文を使用して、JavaファイルをOracle Databaseインスタンスにロードします。Javaファイルは、ファイル・システム、一般的なJava IDE、イントラネットまたはインターネットからアップロードできます。

Javaストアド・プロシージャを作成、ロードおよびコールする手順は、次のとおりです。

- 手順1: Javaクラスの作成または再利用

- 手順2: Javaクラスのロードおよび解決

- 手順3: Javaクラスの公開

- 手順4: ストアド・プロシージャのコール

注意:
Javaストアド・プロシージャを手動でロードするには、CREATE JAVA文を使用できます。たとえば、SQL*Plusでは、CREATE JAVA CLASS文を使用して、ローカルのBFILEおよびLOB列からOracle DatabaseにJavaクラス・ファイルをロードできます。

手順1: Javaクラスの作成または再利用

任意のJava IDEを使用してクラスを作成するか、または必要に応じた既存のクラスを再利用します。Oracle Databaseでは、多数のJava開発ツールおよびクライアント・サイドのプログラム・インタフェースがサポートされます。たとえば、Oracle JVMでは、Oracle JDeveloper、Symantec Visual CafeおよびBorland JBuilderなどの一般的なJava IDEで開発されたプログラムを使用できます。

次の例では、publicクラスOscarを作成します。これには、Oscar Wildeの引用句を戻すquote()という単一のメソッドがあります。

public class Oscar
{
// return a quotation from Oscar Wilde
public static String quote()
{
return "I can resist everything except temptation.";
}
}

クラスをOscar.javaとして保存します。Javaコンパイラを使用して、次のように、.javaファイルをクライアント・システム上でコンパイルします。

javac Oscar.java

コンパイラによって、Javaバイナリ・ファイル(この例の場合はOscar.class)が出力されます。

手順2: Javaクラスのロードおよび解決

loadjavaツールを使用すると、Javaのソース、クラスおよびリソース・ファイルをOracle Databaseインスタンスにロードでき、これらはJavaスキーマ・オブジェクトとして格納されます。loadjavaツールはコマンドラインまたはアプリケーションから実行でき、リゾルバなどいくつかのオプションを指定できます。

次の例では、loadjavaツールがデフォルトのJDBC OCIドライバを使用してデータベースに接続します。ユーザー名とパスワードを指定する必要があります。デフォルトでは、クラスOscarはユーザーのログインするスキーマ(この場合はHR)にロードされます。

$ loadjava -user HR Oscar.class
Password: password

quote()メソッドをコールすると、サーバーはリゾルバを使用して、Stringなどのサポート・クラスを検索します。この場合はデフォルトのリゾルバが使用されます。デフォルトのリゾルバは最初に現行スキーマ内、次に、すべてのコアなJavaクラス・ライブラリが常駐しているSYSスキーマ内を検索します。必要に応じて、別のリゾルバを指定できます。

手順3: Javaクラスの公開

SQLまたはJDBCからコール可能な各Javaメソッドに対して、メソッドのトップレベルのエントリ・ポイントをOracle Databaseに公開するコール仕様を記述する必要があります。通常、必要となるコール仕様は少数です。必要な場合は、Oracle JDeveloperを使用してこれらのコール仕様を生成できます。

次のSQL*Plusの例では、データベースに接続した後、quote()メソッド用のトップレベルのコール仕様を定義します。

SQL> connect HR
Enter password: password

SQL> CREATE FUNCTION oscar_quote RETURN VARCHAR2
2 AS LANGUAGE JAVA
3 NAME 'Oscar.quote() return java.lang.String';

関連項目:
第6章「コール仕様を使用したJavaクラスの公開」

手順4: ストアド・プロシージャのコール

Javaストアド・プロシージャは、JDBC、SQLJ、およびコール仕様にアクセスできるすべてのサード・パーティ言語からコールできます。SQLのCALL文を使用すると、トップレベル(たとえば、SQL*Plus)からストアド・プロシージャをコールできます。ストアド・プロシージャはデータベース・トリガーからもコールできます。

次の例では、SQL*Plusのホスト変数を宣言します。

SQL> VARIABLE theQuote VARCHAR2(50);

この後で、oscar_quote()ファンクションを次のようにコールします。

SQL> CALL oscar_quote() INTO :theQuote;

SQL> PRINT theQuote;

THEQUOTE
--------------------------------------------------
I can resist everything except temptation.

関連項目:
第7章「ストアド・プロシージャのコール」

また、Javaクラスはojvmjavaツールを使用してコールすることもできます。

関連項目:
「ojvmjavaツール」

Javaストアド・プロシージャのデバッグ

Oracle Databaseには、Javaストアド・プロシージャをデバッグするためのJava Debug Wire Protocol (JDWP)インタフェースが用意されています。JDWPは、Java Development Kit (JDK) 1.4以上のバージョンでサポートされています。

JDWPインタフェースでサポートされているいくつかの機能を次に示します。

- 接続のリスニング

- デバッグ中の変数値の変更

- 任意のJava式の評価(メソッド評価など)

- 行上またはメソッド内でのブレークポイントの設定または解除

- コードのステップ実行

- フィールド・アクセスまたは変更ウォッチポイントの設定または解除

注意:
Oracle JDeveloperは、ユーザーが使いやすいようにこれらのデバッグ機能と統合されています。その他の独立系統合開発環境(IDE)ベンダーも、自社のデバッガをOracle Databaseと統合できます。

この項の内容は、次のとおりです。

- Javaストアド・プロシージャのデバッグの前提条件

- jdbデバッガを使用したJavaストアド・プロシージャのデバッグ

- JDeveloperを使用したJavaストアド・プロシージャのデバッグ

Javaストアド・プロシージャのデバッグの前提条件

Javaストアド・プロシージャをデバッグする前に、次の前提条件が満たされていることを確認してください。

- Javaコードをデータベースにデプロイする必要があり、オプションでデバッグ情報を使用してコンパイルできます。

- データベース・ユーザー・アカウントが次の権限を持っている必要があります。

DEBUG ANY PROCEDURE
DEBUG CONNECT SESSION

- 次のようにして、jdwp権限をアクセス制御リスト(ACL)に追加する必要があります。

SQL> begin
2    DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
3      host => <host_name>,
4      ace  => xs$ace_type(privilege_list => xs$name_list('jdwp'),
5                          principal_name => <user_name>,
6                          principal_type => xs_acl.ptype_db));
7  end;
8  /

関連項目:
アクセス制御リストへの権限の追加の詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください。

jdbデバッガを使用したJavaストアド・プロシージャのデバッグ

jdbセッションは、-listen <port>コマンドを使用して開始できます。この方法でセッションを開始した場合、jdbは実行中の仮想マシン(VM)が標準のコネクタを使用して指定のアドレスに接続するのを待機します。

注意:
Javaストアド・プロシージャのデバッグ中、jdbはJVMセッションを開始できず、VMによる接続を待機するのみです。

SQL*PlusなどのOracleクライアントを使用して、デバッガに接続するためのコマンドを発行します。どのクライアントを使用する場合でも、デバッガ接続コマンドを発行するセッションが、Javaストアド・プロシージャを実行するセッションと同じであることを確認する必要があります。たとえば、SQL*Plusを使用している場合は、次のコマンドを発行して、JDWPセッション用に指定したマシンおよびポートへのTCP/IP接続をオープンします。

EXEC DBMS_DEBUG_JDWP.CONNECT_TCP(<host_ip>, <port>)

デバッガが接続を受け入れた後、デバッガ・セッションのブレークポイントを発行し、OracleクライアントでJavaストアド・プロシージャを起動します。これで、デバッガは、指定した最初のブレークポイントで停止します。

JDeveloperを使用したJavaストアド・プロシージャのデバッグ

JDeveloperを使用して、Javaストアド・プロシージャおよびPL/SQLプログラムをシームレスにデバッグできます。PL/SQLプログラムおよびJavaストアド・プロシージャをローカルにデバッグする場合、デバッグを開始するためのコールはJDeveloperから直接行います。JDeveloperによってデバッグ対象のプログラム(デバッグ対象)が自動的に起動され、そのプログラムにデバッガがアタッチされます。

PL/SQLプログラムのリモート・デバッグおよびローカル・デバッグとJavaストアド・プロシージャの主な違いは、デバッグ・セッションの開始方法です。リモート・デバッグの場合は、SQL*PlusなどのOracleクライアント、DBMS_JOBパッケージを使用して作成されたジョブ、OCIプログラムまたはトリガー起動を使用して、デバッグ対象のプログラムを手動で起動する必要があります。その後、デバッグ対象のデータベース・プログラム(デバッグ対象)からJDeveloperデバッガへの接続を確立する必要があります。デバッグ対象プロセスが開始し、JDeveloperのデバッガがプロセスにアタッチされた後は、リモート・デバッグとローカル・デバッグの動作はよく似ています。

注意:
オプションで、デバッグの操作性を向上させるためにJITをオフにすることもできます。

関連項目:
JDeveloperを使用したJavaストアド・プロシージャのデバッグの詳細は、次のページを参照してください。
http://docs.oracle.com/cd/E16162_01/user.1112/e17455/dev_stored_proc.htm#BEJEJIHD

6 コール仕様を使用したJavaクラスの公開

Javaクラスをデータベースにロードしたとき、そのメソッドは自動的には公開されません。これは、Oracle Databaseでは、SQLからのコールに対してどのメソッドが安全なエントリ・ポイントであるか認識されないためです。メソッドを公開するには、Javaメソッド名、パラメータ・タイプおよび戻り型を、対応するSQLにマップするコール仕様を記述する必要があります。この章では、コール仕様を使用したJavaクラスの公開方法について説明します。

この章の内容は、次のとおりです。

- コール仕様の概要

- コール仕様の定義

- トップレベルのコール仕様の作成

- パッケージのコール仕様の記述

- オブジェクト型コール仕様の記述

コール仕様の概要

Javaメソッドを公開するには、コール仕様を作成します。特定のJavaメソッドに対して、SQLのCREATE FUNCTION文またはCREATE PROCEDURE文を使用してファンクションまたはプロシージャのコール仕様を宣言します。PL/SQLパッケージ内またはSQLオブジェクト型内で、同様の宣言を使用します。

値を戻すJavaメソッドはファンクションとして公開し、Javaメソッドvoidはプロシージャとして公開します。ファンクションまたはプロシージャの本体にはLANGUAGE JAVA句が含まれます。この句では、フルネーム、パラメータ・タイプおよび戻り型などのJavaメソッドに関する情報が記録されます。これらの不整合は、実行時まで検出されません。

図6-1に示すように、アプリケーションでは、コール仕様を使用して、つまりコール仕様名を参照することによってJavaメソッドがコールされます。ランタイム・システムでは、Oracleデータ・ディクショナリでコール仕様の定義を検索して、対応するJavaメソッドを実行します。

図6-1 Javaメソッドのコール

別の方法として、ネイティブなJavaインタフェースを使用すると、データベース内のJavaメソッドをJavaクライアントから直接コールできます。

関連項目:
「クライアント側スタブの使用」

コール仕様の定義

コール仕様とそのコール仕様によって公開されるJavaメソッドは、JavaメソッドにPUBLICシノニムがないかぎり、同一スキーマに常駐している必要があります。コール仕様の宣言方法は次のとおりです。

- スタンドアロンPL/SQLファンクションまたはプロシージャ

- パッケージ化されたPL/SQLファンクションまたはプロシージャ

- SQLオブジェクト型のメンバー・メソッド

コール仕様によって、Javaメソッドのトップレベルのエントリ・ポイントがOracle Databaseに公開されます。このため、公開できるのはpublic staticメソッドのみです。ただし、例外が1つあります。インスタンス・メソッドは、SQLオブジェクト型のメンバー・メソッドとして公開できます。

パッケージ化されたコール仕様はトップレベルのコール仕様と同様に機能します。このため、メンテナンスを容易にするために、コール仕様をパッケージ本体に配置することもできます。この方法では、他のスキーマ・オブジェクトを無効にせずにコール仕様を変更できます。また、コール仕様をオーバーロードすることもできます。

この項の内容は、次のとおりです。

- パラメータ・モードの設定

- データ型のマッピング

- サーバー側JDBC内部ドライバの使用

パラメータ・モードの設定

Javaや他のオブジェクト指向言語では、メソッドは引数として渡されたオブジェクトに値を割り当てることはできません。SQLまたはPL/SQLからメソッドをコールするときに引数の値を変更するには、コール仕様でOUTパラメータまたはIN OUTパラメータとして宣言する必要があります。対応するJavaパラメータは、要素の数が1つのみの配列であることが必要です。

要素の値を適切な型の別のJavaオブジェクトに置き換えるか、またはJavaの型によっては値を変更できます。いずれの方法でも、新しい値がコール元に戻されます。たとえば、コール仕様のNUMBER型のOUTパラメータを、float[] pとして宣言されたJavaパラメータにマッピングし、p[0]に新しい値を割り当てます。

注意:
OUTパラメータまたはIN OUTパラメータを宣言するファンクションは、SQLのデータ操作言語(DML)文からはコールできません。

データ型のマッピング

コール仕様では、対応するSQLパラメータとJavaパラメータ、およびファンクションの結果には互換性のあるデータ型を設定する必要があります。

表6-1に、有効なデータ型マッピングが示されています。Oracle Databaseでは、SQL型とJavaクラス間で自動的に変換が行われます。

表6-1 有効なデータ型マッピング

SQL型

Javaクラス

CHAR、VARCHAR2、LONG

java.lang.String

oracle.sql.CHAR

oracle.sql.ROWID

byte[]

NUMBER

boolean

char

byte

byte[]

short

int

long

float

double

java.lang.Byte

java.lang.Short

java.lang.Integer

java.lang.Long

java.lang.Float

java.lang.Double

java.math.BigDecimal

oracle.sql.NUMBER

BINARY_INTEGER

boolean

char

byte

byte[]

short

int

long

BINARY_FLOAT

oracle.sql.BINARY_FLOAT

byte[]

BINARY_DOUBLE

oracle.sql.BINARY_DOUBLE

byte[]

DATE

oracle.sql.DATE

byte[]

RAW

oracle.sql.RAW

byte[]

BLOB

oracle.sql.BLOB

CLOB

oracle.sql.CLOB

BFILE

oracle.sql.BFILE

ROWID

oracle.sql.ROWID

byte[]

TIMESTAMP

oracle.sql.TIMESTAMP

byte[]

TIMESTAMPWITHTIMEZONE

oracle.sql.TIMESTAMPTZ

TIMESTAMPWITHLOCALTIMEZONE

oracle.sql.TIMESTAMPLTZ

ref cursor

java.sql.ResultSet

sqlj.runtime.ResultSetIterator

ユーザー定義の名前付き型、ADT

oracle.sql.STRUCT

opaque名前付き型

oracle.sql.OPAQUE

NESTED TABLEおよびVARRAY名前付き型

oracle.sql.ARRAY

名前付き型の参照

oracle.sql.REF

次の点を考慮する必要もあります。

- 最後の4つのSQL型は、まとめて名前付き型と呼ばれています。

- BLOB、CLOB、BFILE、REF CURSORおよび名前付き型を除くすべてのSQL型は、Javaのバイト配列であるJava型byte[]にマップできます。この場合、引数の変換は、SQL値のRAWバイナリ表現をJavaのバイト配列にコピーする(あるいはその逆へのコピーを行う)ことを意味します。

- ORADataインタフェースおよび関連メソッドを実装するJavaクラス、または表でoracle.sqlクラスのサブクラスとして示されたJavaクラスは、BINARY_INTEGERおよびREF CURSOR以外のSQL型からマップできます。通常はこれを使用して、名前付き型をJPublisherで生成されるJavaクラスにマッピングします。

- UROWID型およびNUMBERのサブタイプ(INTEGER、REALなど)はサポートされていません。

- LONGまたはLONG RAWの列から、32KBを超える値をJavaストアド・プロシージャに取り出すことはできません。

サーバー側JDBC内部ドライバの使用

Java Database Connectivity(JDBC)では、JDBCドライバのセットを管理するDriverManagerクラスを使用して、データベースとの接続を確立します。JDBCドライバがロードされた後、getConnection()メソッドを使用できます。正しいドライバが検出されると、getConnection()メソッドによって、データベース・セッションを表すConnectionオブジェクトが戻されます。SQL文はすべて、そのセッションのコンテキスト内で実行されます。

ただし、サーバー側JDBC内部ドライバは、デフォルトのセッションおよびトランザクション・コンテキスト内で動作します。そのため、すでにデータベースに接続された状態であり、SQL操作はすべてデフォルトのトランザクションの一部です。ドライバは事前に登録されているため、登録する必要はありません。Connectionオブジェクトを取得するには、次のコード行を実行します。

Connection conn = DriverManager.getConnection("jdbc:default:connection:");

INパラメータを取らず、かつ1回のみ実行されるSQL文に対しては、Statementクラスを使用します。Connectionオブジェクト上でcreateStatement()メソッドがコールされると、新しいStatementオブジェクトが戻されます。次に例を示します。

String sql = "DROP " + object_type + " " + object_name;
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);

INパラメータを取るか、または複数回実行されるSQL文に対しては、PreparedStatementクラスを使用します。1つ以上のパラメータ・プレースホルダを含むことができるSQL文は、プリコンパイルされます。疑問符(?)がプレースホルダとして機能します。Connectionオブジェクト上でprepareStatement()メソッドがコールされると、プリコンパイルされたSQL文が含まれる新しいPreparedStatementオブジェクトが戻されます。次に例を示します。

String sql = "DELETE FROM dept WHERE deptno = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, deptID);
pstmt.executeUpdate();

ResultSetオブジェクトには、SQLの問合せ結果、つまり検索条件を満たす行が含まれます。next()メソッドを使用すると次の行に移動し、その行がカレント行になります。カレント行から列の値を取り出すには、getXXX()メソッドを使用します。次に例を示します。

String sql = "SELECT COUNT(*) FROM " + tabName;
int rows = 0;
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(sql);
while (rset.next())
{
rows = rset.getInt(1);
}

CallableStatementオブジェクトを使用すると、ストアド・プロシージャをコールできます。これには、1つの戻りパラメータと任意の数のIN、OUTおよびIN OUTのパラメータを含めることができる、コール・テキストが含まれています。コールは、中カッコ({})で区切られるエスケープ句を使用して記述されます。次の例に示すように、エスケープ構文には3つの形式があります。

// parameterless stored procedure
CallableStatement cstmt = conn.prepareCall("{CALL proc}");

// stored procedure
CallableStatement cstmt = conn.prepareCall("{CALL proc(?,?)}");

// stored function
CallableStatement cstmt = conn.prepareCall("{? = CALL func(?,?)}");

重要な点

ストアド・プロシージャにアクセスするJDBCアプリケーションを開発するときは、次の点を考慮する必要があります。

- 各Oracle JVMセッションには、存在するデータベース・セッションに対して1つの暗黙的なネイティブ接続があります。この接続は概念的で、Javaオブジェクトではありません。これはこのセッションに固有な側面であり、JVM内でオープンまたはクローズできません。

- サーバー側JDBC内部ドライバは、デフォルトのトランザクション・コンテキスト内で動作します。データベースにすでに接続された状態であり、SQL操作はすべてデフォルトのトランザクションの一部です。このトランザクションはローカル・トランザクションで、Java Transaction API(JTA)またはJava Transaction Service(JTS)によって実装されるようなグローバル・トランザクションの一部ではありません。

- 文および結果セットは複数のコールにわたって存続するため、ファイナライザはデータベース・カーソルを解放しません。カーソルが不足しないように、処理が終了した後にすべての文および結果セットをクローズしてください。または、DBAに依頼して、初期化パラメータのOPEN_CURSORSで設定されている制限値を増やすこともできます。

- サーバー側JDBC内部ドライバは、自動コミットをサポートしていません。そのため、アプリケーションで、データベースの変更を明示的にコミットまたはロールバックする必要があります。

- サーバー側JDBC内部ドライバを使用して、リモート・データベースには接続できません。Javaプログラムを実行しているサーバーにのみ接続できます。サーバー/サーバー接続の場合は、サーバー側JDBC Thinドライバを使用します。クライアント/サーバー接続の場合は、クライアント側JDBC ThinドライバまたはJDBC Oracle Call Interface(OCI)ドライバを使用します。

- 通常、デフォルトの接続インスタンスはクローズしないでください。このインスタンスは複数の場所に格納される可能性がある単一インスタンスであり、クローズするとそれぞれの場所が使用できなくなります。クローズすると、それ以降にOracleDriver.defaultConnectionメソッドをコールしたときに、新しいオープン・インスタンスが作成されます。OracleDataSource.getConnectionメソッドはコールするたびに新規オブジェクトを戻しますが、毎回、新しいデータベース接続を作成するわけではありません。同じ暗黙的なネイティブ接続を使用し、同じセッション状態(特にローカル・トランザクション)を共有します。

関連項目:
『Oracle Database JDBC開発者ガイド』

トップレベルのコール仕様の作成

SQL*Plusでは、次の構文を使用してトップレベルのコール仕様を対話形式で定義できます。

CREATE [OR REPLACE]
{ PROCEDURE procedure_name [(param[, param]...)]
| FUNCTION function_name [(param[, param]...)] RETURN sql_type}
[AUTHID {DEFINER | CURRENT_USER}]
[PARALLEL_ENABLE]
[DETERMINISTIC]
{IS | AS} LANGUAGE JAVA
NAME 'method_fullname (java_type_fullname[, java_type_fullname]...)
[return java_type_fullname]';

paramは次の構文で表されます。

parameter_name [IN | OUT | IN OUT] sql_type

AUTHID句は、次の事項を指定します。

- ストアド・プロシージャをその定義者(AUTHID DEFINER)または実行者(AUTHID CURRENT_USER)のどちらの権限を使用して実行するか

- スキーマ・オブジェクトに対する未修飾の参照を定義者と実行者のどちらのスキーマで解決するか

AUTHIDを指定しない場合、デフォルトの動作はDEFINERになり、つまり、ストアド・プロシージャは定義者の権限で実行されます。AUTHIDにCURRENT_USERを指定して、デフォルトの動作をオーバーライドできます。ただし、CURRENT_USERを指定してloadjavaの-definerオプションをオーバーライドすることはできません。

PARALLEL_ENABLEオプションは、ストアド・ファンクションをパラレルDML評価のスレーブ・セッションで安全に使用できることを宣言します。メイン・セッションの状態は、スレーブ・セッションとは共有されません。各スレーブ・セッションには独自の状態があり、セッションの開始時に初期化されます。ファンクションの結果はセッション変数の状態に依存する必要はありません。依存すると、セッション間で結果が異なることがあります。

DETERMINISTICオプションは、オプティマイザによる冗長なファンクション・コールの回避に役立ちます。以前に同じ引数を使用してストアド・ファンクションがコールされた場合、オプティマイザは以前の結果を使用できます。ファンクションの結果はセッション変数またはスキーマ・オブジェクトの状態に依存する必要はありません。依存すると、コール間で結果が異なることがあります。ファンクション索引、またはクエリー・リライトが可能なマテリアライズド・ビューからのみDETERMINISTICファンクションをコールできます。

NAME句の文字列は、Javaメソッドを一意に識別します。Javaの完全修飾名とコール仕様パラメータは、位置によってマッピングされ、対応する必要があります。ただし、この規則はmain()メソッドには適用されません。Javaメソッドが引数を取らない場合は、ファンクションまたはプロシージャ用ではなく、Javaメソッド用の空のパラメータ・リストを作成してください。

Javaの完全修飾名はドット表記法を使用して記述します。次の例では、完全修飾名はドットで区切り、行をまたいで記述できることを示しています。

artificialIntelligence.neuralNetworks.patternClassification.
RadarSignatureClassifier.computeRange()

この項では、次の例を示します。

- 例6-1 簡単なJDBCストアド・プロシージャの公開

- 例6-2 main()メソッドの公開

- 例6-3 整数値を戻すメソッドの公開

- 例6-4 引数の値を切り替えるメソッドの公開

例6-1 簡単なJDBCストアド・プロシージャの公開

次のJavaクラスの実行可能ファイルがデータベースにロードされたとします。

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class GenericDrop
{
public static void dropIt(String object_type, String object_name)
throws SQLException
{
// Connect to Oracle using JDBC driver
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// Build SQL statement
String sql = "DROP " + object_type + " " + object_name;
try
{
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

GenericDropクラスにはdropIt()という名前の1つのメソッドがあり、このメソッドはあらゆる種類のスキーマ・オブジェクトを削除します。たとえば、引数tableおよびemployeesをdropIt()に渡すと、メソッドはデータベース表employeesをスキーマから削除します。

dropIt()メソッドのコール仕様は次のとおりです。

CREATE OR REPLACE PROCEDURE drop_it (obj_type VARCHAR2, obj_name VARCHAR2)
AS LANGUAGE JAVA
NAME 'GenericDrop.dropIt(java.lang.String, java.lang.String)';

Stringに対する参照は完全に修飾する必要があることに注意してください。java.langパッケージはJavaプログラムで自動的に使用できますが、コール仕様で明示的に名前を付ける必要があります。

例6-2 main()メソッドの公開

通常、Java名とコール仕様パラメータは対応する必要があります。ただし、この規則はmain()メソッドには適用されません。そのString[]パラメータは、複数のCHARまたはVARCHAR2のコール仕様パラメータにマッピングできます。引数を表示する次のクラスのmain()メソッドについて考えます。

public class EchoInput
{
public static void main (String[] args)
{
for (int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
}

main()を公開するには、次のコール仕様を記述します。

CREATE OR REPLACE PROCEDURE echo_input(s1 VARCHAR2, s2 VARCHAR2, s3 VARCHAR2)
AS LANGUAGE JAVA
NAME 'EchoInput.main(java.lang.String[])';

コール仕様パラメータに制約(精度、サイズおよびNOT NULLなど)を課すことはできません。そのため、VARCHAR2パラメータの最大サイズは指定できません。ただし、VARCHAR2変数の最大サイズを次のように指定する必要があります。

DECLARE last_name VARCHAR2(20); -- size constraint required

例6-3 整数値を戻すメソッドの公開

次の例では、指定したデータベース表の行数を戻すrowCount()メソッドが公開されます。

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class RowCounter
{
public static int rowCount (String tabName) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "SELECT COUNT(*) FROM " + tabName;
int rows = 0;
try
{
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(sql);
while (rset.next())
{
rows = rset.getInt(1);
}
rset.close();
stmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
return rows;
}
}

コール仕様では、NUMBERのサブタイプ(INTEGER、REALおよびPOSITIVEなど)が許可されていません。そのため、次のコール仕様では、戻り型はNUMBERであり、INTEGERではありません。

CREATE FUNCTION row_count (tab_name VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'RowCounter.rowCount(java.lang.String) return int';

例6-4 引数の値を切り替えるメソッドの公開

引数の値を切り替える、次のSwapperクラスのswap()メソッドについて考えます。

public class Swapper
{
public static void swap (int[] x, int[] y)
{
int hold = x[0];
x[0] = y[0];
y[0] = hold;
}
}

コール仕様によって、swap()メソッドがコール仕様swap()として公開されます。値を渡して戻す必要があるため、このコール仕様ではIN OUT仮パラメータが宣言されます。すべてのコール仕様のOUTパラメータおよびIN OUTパラメータを、Java配列パラメータにマッピングする必要があります。

CREATE PROCEDURE swap (x IN OUT NUMBER, y IN OUT NUMBER)
AS LANGUAGE JAVA
NAME 'Swapper.swap(int[], int[])';

注意:
Javaメソッドとそのコール仕様には同じ名前を設定できます。

パッケージのコール仕様の記述

PL/SQLパッケージは、論理的に関連のある型、項目、サブプログラムをグループ化するスキーマ・オブジェクトです。通常、パッケージには仕様部と本体の2つの部分があります。仕様部はアプリケーションに対するインタフェースで、型、定数、変数、例外、カーソルおよびサブプログラムを宣言して使用できるようにします。本体は、カーソルとサブプログラムを定義します。

SQL*Plusでは、次の構文を使用してPL/SQLパッケージを対話形式で定義できます。

CREATE [OR REPLACE] PACKAGE package_name
[AUTHID {CURRENT_USER | DEFINER}] {IS | AS}
[type_definition [type_definition] ...]
[cursor_spec [cursor_spec] ...]
[item_declaration [item_declaration] ...]
[{subprogram_spec | call_spec} [{subprogram_spec | call_spec}]...]
END [package_name];

[CREATE [OR REPLACE] PACKAGE BODY package_name {IS | AS}
[type_definition [type_definition] ...]
[cursor_body [cursor_body] ...]
[item_declaration [item_declaration] ...]
[{subprogram_spec | call_spec} [{subprogram_spec | call_spec}]...]
[BEGIN
sequence_of_statements]
END [package_name];]

仕様部にはパブリック宣言が保持されていて、アプリケーションで参照できます。本体には、実装の詳細とプライベート宣言が含まれており、これらはアプリケーションから隠されています。パッケージ本体の宣言部に続いて、オプションの初期化部があります。これには、パッケージ変数を初期化する文が記述されています。これは、初めてパッケージを参照するときに1回のみ実行されます。

パッケージ仕様部で宣言されるコール仕様に、パッケージ本体のサブプログラムと同じシグネチャ(つまり、名前とパラメータのリスト)は設定できません。パッケージ仕様部のすべてのサブプログラムをコール仕様として宣言する場合、パッケージ本体は必要ありません(カーソルを定義するか、初期化部を使用する場合を除きます)。

AUTHID句は、すべてのパッケージ・サブプログラムをその定義者(AUTHID DEFINER、デフォルト)と実行者(AUTHID CURRENT_USER)のどちらの権限を使用して実行するかを指定します。スキーマ・オブジェクトに対する未修飾の参照を定義者と実行者のどちらのスキーマで解決するかも指定します。

例6-5に、パッケージのコール仕様の例を示します。

例6-5 パッケージのコール仕様

新規部門の追加、部門の削除および部門の位置の変更を行うメソッドで構成されたJavaクラスDeptManagerについて考えます。addDept()メソッドは、データベースの順序番号を使用して次の部門番号を取得することに注意してください。これらの3つのメソッドは論理的に関連しているため、それらのコール仕様をPL/SQLパッケージにグループ化できます。

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class DeptManager
{
public static void addDept (String deptName, String deptLoc) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "SELECT deptnos.NEXTVAL FROM dual";
String sql2 = "INSERT INTO dept VALUES (?, ?, ?)";
int deptID = 0;
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rset = pstmt.executeQuery();
while (rset.next())
{
deptID = rset.getInt(1);
}
pstmt = conn.prepareStatement(sql2);
pstmt.setInt(1, deptID);
pstmt.setString(2, deptName);
pstmt.setString(3, deptLoc);
pstmt.executeUpdate();
rset.close();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void dropDept (int deptID) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "DELETE FROM dept WHERE deptno = ?";
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, deptID);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void changeLoc (int deptID, String newLoc) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "UPDATE dept SET loc = ? WHERE deptno = ?";
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, newLoc);
pstmt.setInt(2, deptID);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

addDept()、dropDept()およびchangeLoc()メソッドをパッケージ化するとします。最初に、次のようにパッケージ仕様部を作成する必要があります。

CREATE OR REPLACE PACKAGE dept_mgmt AS
PROCEDURE add_dept (dept_name VARCHAR2, dept_loc VARCHAR2);
PROCEDURE drop_dept (dept_id NUMBER);
PROCEDURE change_loc (dept_id NUMBER, new_loc VARCHAR2);
END dept_mgmt;

次に、Javaメソッドのコール仕様を次のように記述してパッケージ本体を作成する必要があります。

CREATE OR REPLACE PACKAGE BODY dept_mgmt AS
PROCEDURE add_dept (dept_name VARCHAR2, dept_loc VARCHAR2)
AS LANGUAGE JAVA
NAME 'DeptManager.addDept(java.lang.String, java.lang.String)';

PROCEDURE drop_dept (dept_id NUMBER)
AS LANGUAGE JAVA
NAME 'DeptManager.dropDept(int)';

PROCEDURE change_loc (dept_id NUMBER, new_loc VARCHAR2)
AS LANGUAGE JAVA
NAME 'DeptManager.changeLoc(int, java.lang.String)';
END dept_mgmt;

dept_mgmtパッケージのストアド・プロシージャを参照するには、次のように、ドット表記法を使用します。

CALL dept_mgmt.add_dept('PUBLICITY', 'DALLAS');

オブジェクト型コール仕様の記述

SQLでは、オブジェクト指向のプログラミングは、データ構造とそのデータの操作に必要なファンクションおよびプロシージャをカプセル化したユーザー定義のコンポジット・データ型である、オブジェクト型に基づきます。データ構造を形成する変数は属性と呼ばれます。オブジェクト型の動作を特徴づけるファンクションおよびプロシージャはメソッドと呼ばれ、Javaで記述できます。

パッケージと同様に、オブジェクト型には、仕様部と本体の2つの部分があります。仕様部はアプリケーションに対するインタフェースで、一連の属性であるデータ構造と、そのデータの操作に必要な操作方法(メソッド)を宣言します。本体は、PL/SQLサブプログラムの本体またはコール仕様を定義して仕様部を実装します。

仕様部で属性またはコール仕様のみを宣言する場合、本体は必要ありません。すべてのメソッドをJavaで実装する場合は、メソッドのコール仕様をオブジェクト型の仕様部に配置して、本体を省略できます。

SQL*Plusでは、次の構文を使用してSQLオブジェクト型を対話形式で定義できます。

CREATE [OR REPLACE] TYPE type_name
[AUTHID {CURRENT_USER | DEFINER}] {IS | AS} OBJECT (
attribute_name data_type[, attribute_name data_type]...
[{MAP | ORDER} MEMBER {function_spec | call_spec},]
[{MEMBER | STATIC} {subprogram_spec | call_spec}
[, {MEMBER | STATIC} {subprogram_spec | call_spec}]...]
);

[CREATE [OR REPLACE] TYPE BODY type_name {IS | AS}
{ {MAP | ORDER} MEMBER function_body;
| {MEMBER | STATIC} {subprogram_body | call_spec};}
[{MEMBER | STATIC} {subprogram_body | call_spec};]...
END;]

AUTHID句は、そのタイプのすべてのメンバー・メソッドをその定義者(AUTHID DEFINER、デフォルト)と実行者(AUTHID CURRENT_USER)のどちらの権限を使用して実行するかを指定します。スキーマ・オブジェクトに対する未修飾の参照を定義者と実行者のどちらのスキーマで解決するかも指定します。

この項の内容は、次のとおりです。

- 属性の宣言

- メソッドの宣言

属性の宣言

オブジェクト型仕様部では、属性はすべてメソッドの前に宣言する必要があります。また、少なくとも1つの属性を宣言する必要があります。宣言できる属性の最大数は1000個です。メソッドはオプションです。

Java変数と同様に、属性は名前とデータ型で宣言します。名前はオブジェクト型内で一意であることが必要ですが、他のオブジェクト型では再利用できます。データ型は任意のSQL型に設定できますが、LONG、LONG RAW、NCHAR、NVARCHAR2、NCLOB、ROWIDおよびUROWIDには設定できません。

代入演算子またはDEFAULT句を使用して宣言部で属性を初期化することはできません。また、NOT NULL制約を属性に課すこともできません。ただし、制約を課すことができるデータベース表にオブジェクトを格納することはできます。

メソッドの宣言

属性の宣言後に、メソッドを宣言できます。MEMBERメソッドは、オブジェクト型のインスタンスである、SELFと呼ばれる組込みパラメータを受け入れます。暗黙的に宣言されたか明示的に宣言されたかに関係なく、これは常に最初にMEMBERメソッドに渡されるパラメータです。メソッド本体では、SELFはメソッドがコールされたオブジェクトを示します。MEMBERメソッドは、次のように、インスタンスに対してコールされます。

instance_expression.method()

STATICメソッドは、SELFの受入れまたは参照ができず、次のように、インスタンスではなくオブジェクト型に対して起動されます。

object_type_name.method()

STATICでないJavaメソッドをコールする場合は、コール仕様でキーワードMEMBERを指定する必要があります。同様に、STATICのJavaメソッドをコールする場合は、コール仕様でキーワードSTATICを指定する必要があります。

この項の内容は、次のとおりです。

- マップ・メソッドとオーダー・メソッド

- コンストラクタ・メソッド

- 例

マップ・メソッドとオーダー・メソッド

CHARなどのSQLスカラー・データ型の値には、事前定義済の順序があり、これによって他の値と比較できます。ただし、オブジェクト型のインスタンスには事前定義済の順序はありません。これらに順序を付けるには、SQLでユーザー定義のマップ・メソッドをコールします。

SQLは、順序付けを使用してx > yなどのブール式を評価し、DISTINCT、GROUP BYおよびORDER BYの各句に伴う比較を行います。マップ・メソッドは、それらすべてのオブジェクトの順序付けにおけるオブジェクトの相対的な位置を戻します。オブジェクト型に含めることができるマップ・メソッドは1つのみで、戻り型がDATE、NUMBERまたはVARCHAR2のいずれかである、パラメータのないファンクションであることが必要です。

また、2つのオブジェクトを比較するオーダー・メソッドを持つSQLを提供することもできます。オーダー・メソッドでは、2つのパラメータ、つまり組込みパラメータSELFとそれと同じ型の別のオブジェクトのみが使用されます。o1とo2のオブジェクトがある場合は、o1 > o2のような比較によってorderメソッドが自動的にコールされます。メソッドは、負数、0(ゼロ)または正数を戻し、それぞれSELFがもう一方のパラメータと比較して小さい、等しいまたは大きいことを示します。オブジェクト型に含めることができるオーダー・メソッドは1つのみで、それは数値結果を戻すファンクションであることが必要です。

マップ・メソッドまたはオーダー・メソッドのいずれかを宣言できますが、両方を宣言することはできません。どちらかのメソッドを宣言すると、SQLとPL/SQLでオブジェクトを比較できます。ただし、どちらのメソッドも宣言しない場合、比較できるのは、SQLのオブジェクトの等価または非等価のみです。

注意:
同じ型の2つのオブジェクトは、対応する属性の値が等しい場合は等価です。

コンストラクタ・メソッド

オブジェクト型にはすべて、そのオブジェクト型と名前が同じシステム定義のファンクションであるコンストラクタがあります。コンストラクタでは、そのオブジェクト型のインスタンスが初期化されて戻されます。

Oracle Databaseでは、すべてのオブジェクト型に対してデフォルト・コンストラクタが生成されます。コンストラクタの仮パラメータは、オブジェクト型の属性と一致します。つまり、パラメータと属性は同じ順序で宣言され、名前とデータ型が同じです。SQLではコンストラクタは暗黙的にはコールされません。そのため、明示的にコールする必要があります。コンストラクタ・コールは、ファンクション・コールが使用できる場所で使用できます。

注意:
JavaコンストラクタをSQLから起動するには、コンストラクタのコールをstaticメソッドにラップし、対応するコール仕様をオブジェクト型のSTATICメンバーとして宣言する必要があります。

例

この項の各例は、それぞれ前の例に基づきます。まず、部門と従業員を表す2つのSQLオブジェクト型を作成します。最初に、オブジェクト型Departmentの仕様部を記述します。仕様部で宣言されるのは属性のみであるため、本体は必要ありません。仕様部は次のとおりです。

CREATE TYPE Department AS OBJECT (
deptno NUMBER(2),
dname VARCHAR2(14),
loc VARCHAR2(13)
);

次に、オブジェクト型Employeeを作成します。deptno属性には、REFと呼ばれる、Department型のオブジェクトのハンドルが格納されています。REFは、オブジェクト型のインスタンスを格納するデータベース表である、オブジェクト表の中のオブジェクトの位置を示します。REFは、メモリーにある特定のインスタンスのコピーは指し示しません。REFを宣言するには、データ型REFとREFの対象となるオブジェクト型を指定します。Employee型は、次のように作成されます。

CREATE TYPE Employee AS OBJECT (
empno NUMBER(4),
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno REF Department
);

次に、Department型とEmployee型のオブジェクトを格納するSQLオブジェクト表を作成します。Department型のオブジェクトを格納するオブジェクト表deptsを作成します。リレーショナル表deptからデータを選択して、オブジェクト型と同じ名前のシステム定義のファンクションであるコンストラクタに渡すことによって、オブジェクト表にデータを移入します。コンストラクタを使用して、そのオブジェクト型のインスタンスを初期化して戻します。depts表は、次のように作成されます。

CREATE TABLE depts OF Department AS
SELECT Department(deptno, dname, loc) FROM dept;

Employee型のオブジェクトを格納するオブジェクト表empsを作成します。オブジェクト表empsの最後の列は、オブジェクト型Employeeの最後の属性に対応しており、Department型のオブジェクトへの参照が格納されます。この列に参照をフェッチするには、オブジェクト表の行に関連付けられた表の別名を引数として取る、演算子REFを使用します。emps表は、次のように作成されます。

CREATE TABLE emps OF Employee AS
SELECT Employee(e.employee_id, e.first_name, e.job_id, e.manager_id, e.hire_date, e.salary, e.commission_pct,
(SELECT REF(d) FROM departments d WHERE d.department_id = e.department_id))
FROM employees e;

REFを選択すると、オブジェクトのハンドルが戻されます。オブジェクト自体は具体化されません。これを行うには、Oracleオブジェクト参照をサポートするoracle.sql.REFクラスのメソッドを使用できます。このクラスはoracle.sql.Datumのサブクラスで、標準のJDBCインタフェースoracle.jdbc2.Refを拡張します。

oracle.sql.STRUCTクラスの使用

さらに処理を続けて、Javaストアド・プロシージャを次のように記述します。Paymasterクラスには、従業員の賃金を計算する1つのメソッドがあります。oracle.sql.STRUCTクラスで定義されているgetAttributes()メソッドでは、属性の型に対するデフォルトのJDBCマッピングが使用されます。たとえば、NUMBERはBigDecimalにマッピングされます。Paymasterクラスは、次のように作成されます。

import java.sql.*;
import java.io.*;
import oracle.sql.*;
import oracle.jdbc.*;
import oracle.oracore.*;
import oracle.jdbc2.*;
import java.math.*;

public class Paymaster
{
public static BigDecimal wages(STRUCT e) throws java.sql.SQLException
{
// Get the attributes of the Employee object.
Object[] attribs = e.getAttributes();
// Must use numeric indexes into the array of attributes.
BigDecimal sal = (BigDecimal)(attribs[5]); // [5] = sal
BigDecimal comm = (BigDecimal)(attribs[6]); // [6] = comm
BigDecimal pay = sal;
if (comm != null)
pay = pay.add(comm);
return pay;
}
}

wages()メソッドは値を戻すため、そのファンクションのコール仕様を次のように記述します。

CREATE OR REPLACE FUNCTION wages (e Employee) RETURN NUMBER AS
LANGUAGE JAVA
NAME 'Paymaster.wages(oracle.sql.STRUCT) return BigDecimal';

パッケージまたはオブジェクト型の内部で定義されていないため、これはトップレベルのコール仕様です。

SQLDataインタフェースの実装

オブジェクトの属性にさらに自然にアクセスできるように、SQLDataインタフェースを実装するJavaクラスを作成します。Javaクラスを作成するには、SQLDataインタフェースで定義されているとおりに、readSQL()およびwriteSQL()メソッドを提供する必要があります。JDBCドライバはreadSQL()メソッドをコールして、データベースの値のストリームを読み取り、Javaクラスのインスタンスに移入します。次の例では、Paymasterを変更して、raiseSal()という2番目のメソッドを追加します。

import java.sql.*;
import java.io.*;
import oracle.sql.*;
import oracle.jdbc.*;
import oracle.oracore.*;
import oracle.jdbc2.*;
import java.math.*;

public class Paymaster implements SQLData
{
// Implement the attributes and operations for this type.
private BigDecimal empno;
private String ename;
private String job;
private BigDecimal mgr;
private Date hiredate;
private BigDecimal sal;
private BigDecimal comm;
private Ref dept;

public static BigDecimal wages(Paymaster e)
{
BigDecimal pay = e.sal;
if (e.comm != null)
pay = pay.add(e.comm);
return pay;
}

public static void raiseSal(Paymaster[] e, BigDecimal amount)
{
e[0].sal = // IN OUT passes [0]
e[0].sal.add(amount); // increase salary by given amount
}

// Implement SQLData interface.

private String sql_type;

public String getSQLTypeName() throws SQLException
{
return sql_type;
}

public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
empno = stream.readBigDecimal();
ename = stream.readString();
job = stream.readString();
mgr = stream.readBigDecimal();
hiredate = stream.readDate();
sal = stream.readBigDecimal();
comm = stream.readBigDecimal();
dept = stream.readRef();
}

public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(empno);
stream.writeString(ename);
stream.writeString(job);
stream.writeBigDecimal(mgr);
stream.writeDate(hiredate);
stream.writeBigDecimal(sal);
stream.writeBigDecimal(comm);
stream.writeRef(dept);
}
}

パラメータがOracle.sql.STRUCTからPaymasterに変更されたため、wages()のコール仕様を次のように変更する必要があります。

CREATE OR REPLACE FUNCTION wages (e Employee) RETURN NUMBER AS
LANGUAGE JAVA
NAME 'Paymaster.wages(Paymaster) return BigDecimal';

新しいraiseSal()メソッドは戻り値がvoidであるため、そのプロシージャのコール仕様を次のように記述します。

CREATE OR REPLACE PROCEDURE raise_sal (e IN OUT Employee, r NUMBER)
AS LANGUAGE JAVA
NAME 'Paymaster.raiseSal(Paymaster[], java.math.BigDecimal)';

このコール仕様もトップレベルです。

オブジェクト型メソッドの実装

トップレベルのコール仕様wagesおよびraise_salを削除し、それらをオブジェクト型Employeeのメソッドとして再宣言するとします。オブジェクト型の仕様部では、すべてのメソッドを属性の後に宣言する必要があります。仕様部で宣言されるのは属性とコール仕様のみであるため、オブジェクト型の本体は必要ありません。Employeeオブジェクト型は、次のように再作成できます。

CREATE TYPE Employee AS OBJECT (
empno NUMBER(4),
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno REF Department
MEMBER FUNCTION wages RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Paymaster.wages() return java.math.BigDecimal',
MEMBER PROCEDURE raise_sal (r NUMBER)
AS LANGUAGE JAVA
NAME 'Paymaster.raiseSal(java.math.BigDecimal)'
);

次に、この変更に応じてPaymasterを変更します。SQLパラメータSELFは直接Javaパラメータthisに対応しているため、SELFがIN OUT(プロシージャのデフォルト)として宣言されている場合でも、配列をraiseSal()に渡す必要はありません。

import java.sql.*;
import java.io.*;
import oracle.sql.*;
import oracle.jdbc.*;
import oracle.oracore.*;
import oracle.jdbc2.*;
import java.math.*;

public class Paymaster implements SQLData
{
// Implement the attributes and operations for this type.
private BigDecimal empno;
private String ename;
private String job;
private BigDecimal mgr;
private Date hiredate;
private BigDecimal sal;
private BigDecimal comm;
private Ref dept;

public BigDecimal wages()
{
BigDecimal pay = sal;
if (comm != null)
pay = pay.add(comm);
return pay;
}

public void raiseSal(BigDecimal amount)
{
// For SELF/this, even when IN OUT, no array is needed.
sal = sal.add(amount);
}

// Implement SQLData interface.

String sql_type;

public String getSQLTypeName() throws SQLException
{
return sql_type;
}

public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
empno = stream.readBigDecimal();
ename = stream.readString();
job = stream.readString();
mgr = stream.readBigDecimal();
hiredate = stream.readDate();
sal = stream.readBigDecimal();
comm = stream.readBigDecimal();
dept = stream.readRef();
}

public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(empno);
stream.writeString(ename);
stream.writeString(job);
stream.writeBigDecimal(mgr);
stream.writeDate(hiredate);
stream.writeBigDecimal(sal);
stream.writeBigDecimal(comm);
stream.writeRef(dept);
}
}

7 ストアド・プロシージャのコール

Javaストアド・プロシージャは、ロードして公開した後にコールできます。この章では、Javaストアド・プロシージャを様々なコンテキストでコールする方法について説明します。Oracle JVMによるSQL例外の処理方法についても説明します。

この章の内容は、次のとおりです。

- トップレベルからのJavaのコール

- データベース・トリガーからのJavaのコール

- SQL DMLからのJavaのコール

- PL/SQLからのJavaのコール

- JavaからのPL/SQLのコール

- Oracle JVMによる例外の処理方法

トップレベルからのJavaのコール

SQLのCALL文を使用すると、トップレベルで公開されたJavaメソッドを、PL/SQLパッケージまたはSQLオブジェクト型でコールできます。SQL*Plusでは、次の構文を使用してCALL文を対話形式で実行できます。

CALL [schema_name.][{package_name | object_type_name}][@dblink_name]
{ procedure_name ([param[, param]...])
| function_name ([param[, param]...]) INTO :host_variable};

paramは次の構文で表されます。

{literal | :host_variable}

ホスト変数は、ホスト環境で宣言された変数です。このホスト変数には接頭辞としてコロンを付ける必要があります。次の例は、同じCALL文ではホスト変数を2度使用できないこと、およびパラメータのないサブプログラムは空のパラメータ・リストを使用してコールする必要があることを示しています。

CALL swap(:x, :x); -- illegal, duplicate host variables
CALL balance() INTO :current_balance; -- () required

この項の内容は、次のとおりです。

- 出力のリダイレクト

- トップレベルからのJavaストアド・プロシージャのコールの例

出力のリダイレクト

サーバーでのデフォルトの出力デバイスは、ユーザー・スクリーンではなくトレース・ファイルです。このため、System.outおよびSystem.errは、現行のトレース・ファイルに出力されます。出力をSQL*Plusテキスト・バッファにリダイレクトするには、次のようにDBMS_JAVAパッケージのset_output()プロシージャをコールする必要があります。

SQL> SET SERVEROUTPUT ON
SQL> CALL dbms_java.set_output(2000);

最小バッファ・サイズは2,000バイト(デフォルト・サイズ)で、最大バッファ・サイズは1,000,000バイトです。次の例では、バッファ・サイズを5,000バイトに増やしています。

SQL> SET SERVEROUTPUT ON SIZE 5000
SQL> CALL dbms_java.set_output(5000);

出力はストアド・プロシージャの終了時に表示されます。

トップレベルからのJavaストアド・プロシージャのコールの例

この項では、次の例を示します。

- 例7-1 簡単なJDBCストアド・プロシージャ

- 例7-2 フィボナッチ数列

例7-1 簡単なJDBCストアド・プロシージャ

次の例にあるmain()メソッドは、データベース表の名前(employeesなど)、および条件(salary > 1500など)を指定するオプションのWHERE句を受け入れます。条件を省略した場合、メソッドは表からすべての行を削除し、条件を指定した場合は、その条件を満たす行のみを削除します。

import java.sql.*;
import oracle.jdbc.*;

public class Deleter
{
public static void main (String[] args) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "DELETE FROM " + args[0];
if (args.length > 1)
sql += " WHERE " + args[1];
try
{
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

main()メソッドには、1つまたは2つの引数を指定できます。通常は、DEFAULT句を使用して、PL/SQLサブプログラムに渡す引数の数を変更します。ただし、この句はコール仕様では使用できません。そのため、次のように2つのパッケージ・プロシージャをオーバーロードする必要があります。

CREATE OR REPLACE PACKAGE pkg AS
PROCEDURE delete_rows (table_name VARCHAR2);
PROCEDURE delete_rows (table_name VARCHAR2, condition VARCHAR2);
END;

CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE delete_rows (table_name VARCHAR2)
AS LANGUAGE JAVA
NAME 'Deleter.main(java.lang.String[])';

PROCEDURE delete_rows (table_name VARCHAR2, condition VARCHAR2)
AS LANGUAGE JAVA
NAME 'Deleter.main(java.lang.String[])';
END;

これで、次のようにdelete_rowsプロシージャをコールできます。

SQL> CALL pkg.delete_rows('employees', 'salary > 1500');

Call completed.

SQL> SELECT first_name, salary FROM employees;

FIRST_NAME  SALARY
--------- --------
SMITH          800
WARD          1250
MARTIN        1250
TURNER        1500
ADAMS         1100
JAMES          950
MILLER        1300

7 rows selected.

注意:
トップレベルのプロシージャはオーバーロードできません。

例7-2 フィボナッチ数列

次のJavaクラスの実行可能ファイルがOracle Databaseに格納されているとします。

public class Fibonacci
{
public static int fib (int n)
{
if (n == 1 || n == 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
}

Fibonacciクラスにはfib()という名前のメソッドが1つあり、このメソッドはn番目のフィボナッチ数を戻します。フィボナッチ数列(1、1、2、3、5、8、13、21、...)は、再帰的です。数列の各項目(2番目の項目より後)は、直前の2つの項目の合計値です。fib()は値を戻すため、次のようにファンクションとして公開する必要があります。

CREATE OR REPLACE FUNCTION fib (n NUMBER) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'Fibonacci.fib(int) return int';

次に、2つのSQL*Plusホスト変数を宣言し、最初の変数を初期化します。

SQL> VARIABLE n NUMBER
SQL> VARIABLE f NUMBER
SQL> EXECUTE :n := 7;

PL/SQL procedure successfully completed.

これで、fib()ファンクションをコールできます。CALL文では、ホスト変数に接頭辞としてコロンを付ける必要があります。このファンクションは次のようにコールできます。

SQL> CALL fib(:n) INTO :f;

Call completed.

SQL> PRINT f

F
----------
13

データベース・トリガーからのJavaのコール

データベース・トリガーは、特定の表またはビューに関連付けられたストアド・プログラムです。Oracle Databaseでは、データ操作言語(DML)操作によって表またはビューが影響されると、トリガーが自動的に実行されます。

トリガー・イベントが発生すると、トリガーが実行され、PL/SQLブロックまたはCALL文によってアクションが実行されます。トリガー・イベントの前または後に、文トリガーが1回実行されます。トリガー・イベントの影響を受けた各行に対して、行トリガーが1回実行されます。

データベース・トリガー内では、相関名newおよびoldを使用して、変更する行の新旧の値を参照できます。トリガー・アクション・ブロックまたはCALL文では、列名に:newまたは:oldを接頭辞として付ける必要があります。

次に、データベース・トリガーからのJavaストアド・プロシージャのコールの例を示します。

- 例7-3 データベース・トリガーからのJavaストアド・プロシージャのコール - I

- 例7-4 データベース・トリガーからのJavaストアド・プロシージャのコール - II

例7-3 データベース・トリガーからのJavaストアド・プロシージャのコール - I

次のJavaクラスを使用して、一定以上の給与増加を記録するデータベース・トリガーを作成するとします。

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class DBTrigger
{
public static void logSal (int empID, float oldSal, float newSal)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "INSERT INTO sal_audit VALUES (?, ?, ?)";
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, empID);
pstmt.setFloat(2, oldSal);
pstmt.setFloat(3, newSal);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

DBTriggerクラスには、sal_audit表に行を挿入するlogSal()メソッドが1つあります。logSal()はvoidメソッドであるため、次のようにプロシージャとして公開する必要があります。

CREATE OR REPLACE PROCEDURE log_sal (
emp_id NUMBER,
old_sal NUMBER,
new_sal NUMBER
)
AS LANGUAGE JAVA
NAME 'DBTrigger.logSal(int, float, float)';

次に、sal_audit表を次のように作成します。

CREATE TABLE sal_audit (
empno NUMBER,
oldsal NUMBER,
newsal NUMBER
);

最後に、給与の増加が20パーセントを超えたときに起動するデータベース・トリガーを作成します。

CREATE OR REPLACE TRIGGER sal_trig
AFTER UPDATE OF salary ON employees
FOR EACH ROW
WHEN (new.salary > 1.2 * old.salary)
CALL log_sal(:new.employee_id, :old.salary, :new.salary);

次のUPDATE文を実行すると、employees表のすべての行が更新されます。

SQL> UPDATE employee SET salary = salary + 300;

トリガーのWHEN句の条件セットを満たす各行に対してトリガーが実行され、Javaメソッドがsal_audit表に行を挿入します。

SQL> SELECT * FROM sal_audit;

EMPNO     OLDSAL     NEWSAL
---------- ---------- ----------
7369        800       1100
7521       1250       1550
7654       1250       1550
7876       1100       1400
7900        950       1250
7934       1300       1600

6 rows selected.

例7-4 データベース・トリガーからのJavaストアド・プロシージャのコール - II

次のように定義されたデータベース・ビューに行を挿入するトリガーを作成するとします。

CREATE VIEW emps AS
SELECT empno, ename, 'Sales' AS dname FROM sales
UNION ALL
SELECT empno, ename, 'Marketing' AS dname FROM mktg;

データベース表salesおよびmktgは次のように定義されています。

CREATE TABLE sales (empno NUMBER(4), ename VARCHAR2(10));
CREATE TABLE mktg (empno NUMBER(4), ename VARCHAR2(10));

UNION ALLなどの集合演算子を使用するビューには行を挿入できないため、INSTEAD OFトリガーを作成する必要があります。このトリガーを作成しないと、複数の行が実表に挿入されます。

最初に、次のJavaメソッドを例7-3で定義したDBTriggerクラスに追加します。

public static void addEmp (int empNo, String empName, String deptName)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String tabName = (deptName.equals("Sales") ? "sales" : "mktg");
String sql = "INSERT INTO " + tabName + " VALUES (?, ?)";
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, empNo);
pstmt.setString(2, empName);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

addEmp()メソッドは、deptNameパラメータの値に応じて、sales表またはmktg表に行を挿入します。このメソッドのコール仕様は、次のように作成します。

CREATE OR REPLACE PROCEDURE add_emp (
emp_no NUMBER,
emp_name VARCHAR2,
dept_name VARCHAR2
)
AS LANGUAGE JAVA
NAME 'DBTrigger.addEmp(int, java.lang.String, java.lang.String)';

次に、INSTEAD OFトリガーを次のように作成します。

CREATE OR REPLACE TRIGGER emps_trig
INSTEAD OF INSERT ON emps
FOR EACH ROW
CALL add_emp(:new.empno, :new.ename, :new.dname);

次の各INSERT文を実行すると、トリガーが実行され、Javaメソッドによって、行が適切な実表に挿入されます。

SQL> INSERT INTO emps VALUES (8001, 'Chand', 'Sales');
SQL> INSERT INTO emps VALUES (8002, 'Van Horn', 'Sales');
SQL> INSERT INTO emps VALUES (8003, 'Waters', 'Sales');
SQL> INSERT INTO emps VALUES (8004, 'Bellock', 'Marketing');
SQL> INSERT INTO emps VALUES (8005, 'Perez', 'Marketing');
SQL> INSERT INTO emps VALUES (8006, 'Foucault', 'Marketing');

SQL> SELECT * FROM sales;

EMPNO ENAME
---------- ----------
8001 Chand
8002 Van Horn
8003 Waters

SQL> SELECT * FROM mktg;

EMPNO ENAME
---------- ----------
8004 Bellock
8005 Perez
8006 Foucault

SQL> SELECT * FROM emps;

EMPNO ENAME      DNAME
---------- ---------- ---------
8001 Chand      Sales
8002 Van Horn   Sales
8003 Waters     Sales
8004 Bellock    Marketing
8005 Perez      Marketing
8006 Foucault   Marketing

SQL DMLからのJavaのコール

ファンクションとして公開するJavaメソッドは、SQLのSELECT、INSERT、UPDATE、DELETE、CALL、EXPLAIN PLAN、LOCK TABLEおよびMERGEの各文からコールできます。たとえば、次のJavaクラスの実行可能ファイルがOracle Databaseに格納されているとします。

public class Formatter
{
public static String formatEmp (String empName, String jobTitle)
{
empName = empName.substring(0,1).toUpperCase() +
empName.substring(1).toLowerCase();
jobTitle = jobTitle.toLowerCase();
if (jobTitle.equals("analyst"))
return (new String(empName + " is an exempt analyst"));
else
return (new String(empName + " is a non-exempt " + jobTitle));
}
}

Formatterクラスには、formatEmp()メソッドがあり、これは、従業員の名前と役職を含むフォーマットされた文字列を戻します。このメソッドのコール仕様は、次のように作成します。

CREATE OR REPLACE FUNCTION format_emp (ename VARCHAR2, job VARCHAR2)
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'Formatter.formatEmp (java.lang.String, java.lang.String)
return java.lang.String';

次に、format_empファンクションをコールして従業員のリストをフォーマットします。

SQL> SELECT format_emp(first_name, job_id) AS "Employees" FROM employees
2   WHERE job_id NOT IN ('AC_MGR', 'AD_PRES') ORDER BY first_name;

Employees
--------------------------------------------
Adams is a non-exempt clerk
Allen is a non-exempt salesman
Ford is an exempt analyst
James is a non-exempt clerk
Martin is a non-exempt salesman
Miller is a non-exempt clerk
Scott is an exempt analyst
Smith is a non-exempt clerk
Turner is a non-exempt salesman
Ward is a non-exempt salesman

制限事項

Javaメソッドは次の規則に準拠する必要があります。これらの規則は、副作用を制御することを意図しています。

- SELECT文またはパラレル化したINSERT、UPDATEまたはDELETEの各文からコールしたメソッドでは、データベース表を変更できません。

- INSERT、UPDATEまたはDELETEの各文からコールしたメソッドでは、その文で変更されたデータベース表に対する問合せや変更はできません。

- SELECT、INSERT、UPDATEまたはDELETEの各文からコールしたメソッドでは、SQLトランザクション制御文(COMMITなど)、セッション制御文(SET ROLEなど)またはシステム制御文(ALTER SYSTEMなど)を実行できません。また、このメソッドでは、CREATEなどのデータ定義言語(DDL)文の後に自動コミットが続くため、この文も実行できません。

メソッド内のSQL文が前述の規則に違反している場合は、実行時にエラーが発生します。

PL/SQLからのJavaのコール

Javaストアド・プロシージャは、あらゆるPL/SQLブロック、サブプログラムまたはパッケージからコールできます。たとえば、次のJavaクラスの実行可能ファイルがOracle Databaseに格納されているとします。

import java.sql.*;
import oracle.jdbc.*;

public class Adjuster
{
public static void raiseSalary (int empNo, float percent) throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
String sql = "UPDATE employees SET salary = salary * ? WHERE employee_id = ?";
try
{
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setFloat(1, (1 + percent / 100));
pstmt.setInt(2, empNo);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

Adjusterクラスには、指定した割合で従業員の給与を上げるメソッドが1つあります。raiseSalary()はvoidメソッドであるため、次のようにプロシージャとして公開する必要があります。

CREATE OR REPLACE PROCEDURE raise_salary (empno NUMBER, pct NUMBER)
AS LANGUAGE JAVA
NAME 'Adjuster.raiseSalary(int, float)';

次の例では、無名PL/SQLブロックからraise_salaryプロシージャをコールします。

DECLARE
emp_id NUMBER;
percent NUMBER;
BEGIN
-- get values for emp_id and percent
raise_salary(emp_id, percent);
...
END;

次の例では、スタンドアロンPL/SQLストアド・プロシージャから例6-3で定義したrow_countファンクションをコールします。

CREATE PROCEDURE calc_bonus (emp_id NUMBER, bonus OUT NUMBER) AS
emp_count NUMBER;
...
BEGIN
emp_count := row_count('employees');
...
END;

次の例では、無名PL/SQLブロックから「オブジェクト型メソッドの実装」で定義したオブジェクト型Employeeのraise_salメソッドをコールします。

DECLARE
emp_id NUMBER(4);
v emp_type;
BEGIN
-- assign a value to emp_id
SELECT VALUE(e) INTO v FROM emps e WHERE empno = emp_id;
v.raise_sal(500);
UPDATE emps e SET e = v WHERE empno = emp_id;
...
END;

JavaからのPL/SQLのコール

Java Database Connectivity(JDBC)およびSQLJを使用すると、PL/SQLストアド・ファンクションおよびPL/SQLストアド・プロシージャをコールできます。たとえば、指定した銀行口座の残高を戻す、次のストアド・ファンクションをコールするとします。

FUNCTION balance (acct_id NUMBER) RETURN NUMBER IS
acct_bal NUMBER;
BEGIN
SELECT bal INTO acct_bal FROM accts
WHERE acct_no = acct_id;
RETURN acct_bal;
END;

JDBCプログラムでは、balanceファンクションのコールを次のように作成できます。

...
CallableStatement cstmt = conn.prepareCall("{? = CALL balance(?)}");
cstmt.registerOutParameter(1, Types.FLOAT);
cstmt.setInt(2, acctNo);
cstmt.executeUpdate();
float acctBal = cstmt.getFloat(1);
...

SQLJプログラムでは、このコールを次のように作成できます。

...
#sql acctBal = {VALUES(balance(:IN acctNo))};
...

Oracle JVMによる例外の処理方法

Java例外はオブジェクトであり、ネーミングと継承の階層があります。そのため、サブ例外(例外クラスのサブクラス)をスーパー例外(例外クラスのスーパークラス)のかわりに使用できます。

すべてのJava例外オブジェクトはtoString()メソッドをサポートしており、これは、オプションの文字列に連結した例外クラスの完全修飾名を戻します。一般に、この文字列には、例外条件に関するデータ依存情報が含まれています。通常、例外を構成するコードは、この文字列を例外に対応付けます。

Javaストアド・プロシージャでSQL文が実行されると、スローされた例外は、そのプロシージャに対してjava.sql.SQLExceptionのサブクラスとして作成されます。このクラスには、getErrorCode()およびgetMessage()メソッドがあり、これらのメソッドは、それぞれOracleエラー・コードおよびエラー・メッセージを戻します。

SQLまたはPL/SQLからコールされたストアド・プロシージャがJavaで捕捉されない例外をスローした場合は、次のエラー・メッセージが表示されます。

ORA-29532 Java call terminated by uncaught Java exception

このエラー・メッセージによって、捕捉されない例外が(SQL以外の例外を含めて)すべてレポートされます。

8 Javaストアド・プロシージャのアプリケーションの例

この章では、ストアド・プロシージャを使用したJavaアプリケーションの作成方法について説明します。

この章では、設計フェーズから実際の実装に至るまで、サンプル・アプリケーションの開発手順を示します。

- データベース・スキーマの計画

- データベース表の作成

- Javaクラスの作成

- Javaクラスのロード

- Javaクラスの公開

- Javaストアド・プロシージャのコール

データベース・スキーマの計画

この例の目的は、顧客の発注書を管理する簡単なシステムを開発することです。このために、データベース・スキーマ計画を作成する必要があります。最初に、関連するビジネス・エンティティおよびそれらの関係を指定します。この例での基本的なエンティティは、顧客、発注書、明細項目および在庫品目です。したがって、スキーマに次の表を含めることができます。

- Customers

- Orders

- LineItems

- StockItems

顧客が1つまたは複数の注文を行うことができるのに対し、特定の発注書を発行できるのは1人の顧客のみであるため、Customer表とOrders表との間には1対多の関係があります。顧客がいない状態での発注があるため、この関係はオプションです。たとえば、以前に顧客として定義されていない顧客が発注するような場合です。

1枚の発注書には複数の在庫品目を指定する場合があり、在庫品目は複数の発注書によって指定される場合があるため、Orders表とStockItems表との間には多対多の関係があります。ただし、発注書と在庫品目の参照関係は不明です。したがって、明細項目の概念が必要です。発注書には複数の明細項目が記載される場合がありますが、特定の明細項目を記載できるのは1枚の発注書のみなので、Orders表とLineItems表との間には1対多の関係があります。

明細項目に指定できるのは1つの在庫品目のみですが、特定の在庫品目は複数の明細項目によって指定される場合があるため、LineItemsとStockItems表との間には多対1の関係があります。明細項目がない状態での在庫品目の指定があるため、この関係はオプションです。

図8-1は、複数の表の関係を示しています。スキーマ計画では、主キーと外部キーを使用してこれらの関係を設定します。

主キーは、表の各行を一意に識別する値を持つ列または列の組合せです。外部キーは、他の表の主キーと一致する値を持つ列または列の組合せです。たとえば、LineItems表のPONo列は、Orders表の主キーと一致する外部キーです。LineItems.PONo列の発注書番号はすべてOrders.PONo列にも存在する必要があります。

図8-1 発注書アプリケーションのスキーマ計画

データベース表の作成

データベース・スキーマを計画した後は、スキーマ計画にデータベース表を作成します。次のようにして、Customers表を定義します。

CREATE TABLE Customers (
CustNo NUMBER(3) NOT NULL,
CustName VARCHAR2(30) NOT NULL,
Street VARCHAR2(20) NOT NULL,
City VARCHAR2(20) NOT NULL,
State CHAR(2) NOT NULL,
Zip VARCHAR2(10) NOT NULL,
Phone VARCHAR2(12),
PRIMARY KEY (CustNo)
);

Customers表には、顧客に関する情報が格納されます。必須情報は、NOT NULLとして定義されます。たとえば、すべての顧客には出荷先の住所が必要です。ただし、Customers表では、顧客とその発注書との関係は管理されません。したがって、この関係は、次のように定義可能なOrders表で管理する必要があります。

CREATE TABLE Orders (
PONo NUMBER(5),
Custno NUMBER(3) REFERENCES Customers,
OrderDate DATE,
ShipDate DATE,
ToStreet VARCHAR2(20),
ToCity VARCHAR2(20),
ToState CHAR(2),
ToZip VARCHAR2(10),
PRIMARY KEY (PONo)
);

明細項目は、発注書および在庫品目との関係があります。LineItems表では、外部キーを使用してこれらの関係を管理します。たとえば、LineItems表のStockNo外部キー列はStockItems表のStockNo主キー列を参照しますが、これは次のようにして定義できます。

CREATE TABLE StockItems (
StockNo NUMBER(4) PRIMARY KEY,
Description VARCHAR2(20),
Price NUMBER(6,2))
);

Orders表は、Customers表のCustNo主キー列を参照しているCustNo外部キー列を使用して、顧客と発注書との関係を管理します。ただし、Orders表では、発注書とその明細項目との間の関係を管理しません。したがって、この関係は、次のように定義可能なLineItems表で管理する必要があります。

CREATE TABLE LineItems (
LineNo NUMBER(2),
PONo NUMBER(5) REFERENCES Orders,
StockNo NUMBER(4) REFERENCES StockItems,
Quantity NUMBER(2),
Discount NUMBER(4,2),
PRIMARY KEY (LineNo, PONo)
);

Javaクラスの作成

データベース表を作成した後は、発注書システムに必要な操作を考慮して、適切なJavaメソッドを作成します。前述の例で定義した表に基づいた簡単なシステムでは、顧客の登録、部品の保管、発注の入力などのメソッドが必要です。これらのメソッドは、JavaクラスPOManagerで次のように実装できます。

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class POManager
{
public static void addCustomer (int custNo, String custName, String street,
String city, String state, String zipCode, String phoneNo) throws SQLException
{
String sql = "INSERT INTO Customers VALUES (?,?,?,?,?,?,?)";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, custNo);
pstmt.setString(2, custName);
pstmt.setString(3, street);
pstmt.setString(4, city);
pstmt.setString(5, state);
pstmt.setString(6, zipCode);
pstmt.setString(7, phoneNo);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void addStockItem (int stockNo, String description, float price)
throws SQLException
{
String sql = "INSERT INTO StockItems VALUES (?,?,?)";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, stockNo);
pstmt.setString(2, description);
pstmt.setFloat(3, price);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void enterOrder (int orderNo, int custNo, String orderDate,
String shipDate, String toStreet, String toCity, String toState,
String toZipCode) throws SQLException
{
String sql = "INSERT INTO Orders VALUES (?,?,?,?,?,?,?,?)";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, orderNo);
pstmt.setInt(2, custNo);
pstmt.setString(3, orderDate);
pstmt.setString(4, shipDate);
pstmt.setString(5, toStreet);
pstmt.setString(6, toCity);
pstmt.setString(7, toState);
pstmt.setString(8, toZipCode);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void addLineItem (int lineNo, int orderNo, int stockNo,
int quantity, float discount) throws SQLException
{
String sql = "INSERT INTO LineItems VALUES (?,?,?,?,?)";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, lineNo);
pstmt.setInt(2, orderNo);
pstmt.setInt(3, stockNo);
pstmt.setInt(4, quantity);
pstmt.setFloat(5, discount);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void totalOrders () throws SQLException
{
String sql = "SELECT O.PONo, ROUND(SUM(S.Price * L.Quantity)) AS TOTAL " +
"FROM Orders O, LineItems L, StockItems S " +
"WHERE O.PONo = L.PONo AND L.StockNo = S.StockNo " +
"GROUP BY O.PONo";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rset = pstmt.executeQuery();
printResults(rset);
rset.close();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

static void printResults (ResultSet rset) throws SQLException
{
String buffer = "";
try
{
ResultSetMetaData meta = rset.getMetaData();
int cols = meta.getColumnCount(), rows = 0;
for (int i = 1; i <= cols; i++)
{
int size = meta.getPrecision(i);
String label = meta.getColumnLabel(i);
if (label.length() > size)
size = label.length();
while (label.length() < size)
label += " ";
buffer = buffer + label + " ";
}
buffer = buffer + "\n";
while (rset.next())
{
rows++;
for (int i = 1; i <= cols; i++)
{
int size = meta.getPrecision(i);
String label = meta.getColumnLabel(i);
String value = rset.getString(i);
if (label.length() > size)
size = label.length();
while (value.length() < size)
value += " ";
buffer = buffer + value + " ";
}
buffer = buffer + "\n";
}
if (rows == 0)
buffer = "No data found!\n";
System.out.println(buffer);
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void checkStockItem (int stockNo) throws SQLException
{
String sql = "SELECT O.PONo, O.CustNo, L.StockNo, " +
"L.LineNo, L.Quantity, L.Discount " +
"FROM Orders O, LineItems L " +
"WHERE O.PONo = L.PONo AND L.StockNo = ?";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, stockNo);
ResultSet rset = pstmt.executeQuery();
printResults(rset);
rset.close();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void changeQuantity (int newQty, int orderNo, int stockNo)
throws SQLException
{
String sql = "UPDATE LineItems SET Quantity = ? " +
"WHERE PONo = ? AND StockNo = ?";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, newQty);
pstmt.setInt(2, orderNo);
pstmt.setInt(3, stockNo);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}

public static void deleteOrder (int orderNo) throws SQLException
{
String sql = "DELETE FROM LineItems WHERE PONo = ?";
try
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, orderNo);
pstmt.executeUpdate();
sql = "DELETE FROM Orders WHERE PONo = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, orderNo);
pstmt.executeUpdate();
pstmt.close();
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
}
}

Javaクラスのロード

Javaクラスを作成した後は、loadjavaツールを使用して、次のようにJavaストアド・プロシージャをOracle Databaseにアップロードします。

> loadjava -u HR@myPC:1521:orcl -v -r -t POManager.java
Password: password
initialization complete
loading : POManager
creating : POManager
resolver : resolver ( ("*" HR) ("*" public) ("*" -) )
resolving: POManager

-vオプションを指定すると、冗長モードになります。-rオプションを指定すると、アップロードしたJavaソース・ファイルがコンパイルされ、そのクラスの外部参照が解決されます。-tオプションを指定すると、loadjavaツールは、クライアント側のJDBC Thinドライバを使用してデータベースに接続します。

Javaクラスの公開

Javaクラスをロードした後は、Javaストアド・プロシージャをOracleデータ・ディクショナリに公開します。これを行うには、Javaメソッド名、パラメータ・タイプおよび戻り型を、対応するSQLにマップするコール仕様を記述する必要があります。

POManager Javaクラスのメソッドは論理的に関連付けられています。そのため、PL/SQLパッケージ内でコール仕様をグループ化できます。グループ化するには、最初に、次のようにパッケージ仕様部を作成します。

CREATE OR REPLACE PACKAGE po_mgr AS
PROCEDURE add_customer (cust_no NUMBER, cust_name VARCHAR2,
street VARCHAR2, city VARCHAR2, state CHAR, zip_code VARCHAR2,
phone_no VARCHAR2);
PROCEDURE add_stock_item (stock_no NUMBER, description VARCHAR2,
price NUMBER);
PROCEDURE enter_order (order_no NUMBER, cust_no NUMBER,
order_date VARCHAR2, ship_date VARCHAR2, to_street VARCHAR2,
to_city VARCHAR2, to_state CHAR, to_zip_code VARCHAR2);
PROCEDURE add_line_item (line_no NUMBER, order_no NUMBER,
stock_no NUMBER, quantity NUMBER, discount NUMBER);
PROCEDURE total_orders;
PROCEDURE check_stock_item (stock_no NUMBER);
PROCEDURE change_quantity (new_qty NUMBER, order_no NUMBER,
stock_no NUMBER);
PROCEDURE delete_order (order_no NUMBER);
END po_mgr;

次に、Javaメソッドのコール仕様を次のように記述してパッケージ本体を作成します。

CREATE OR REPLACE PACKAGE BODY po_mgr AS
PROCEDURE add_customer (cust_no NUMBER, cust_name VARCHAR2,
street VARCHAR2, city VARCHAR2, state CHAR, zip_code VARCHAR2,
phone_no VARCHAR2) AS LANGUAGE JAVA
NAME 'POManager.addCustomer(int, java.lang.String,
java.lang.String, java.lang.String, java.lang.String,
java.lang.String, java.lang.String)';

PROCEDURE add_stock_item (stock_no NUMBER, description VARCHAR2,
price NUMBER) AS LANGUAGE JAVA
NAME 'POManager.addStockItem(int, java.lang.String, float)';

PROCEDURE enter_order (order_no NUMBER, cust_no NUMBER,
order_date VARCHAR2, ship_date VARCHAR2, to_street VARCHAR2,
to_city VARCHAR2, to_state CHAR, to_zip_code VARCHAR2)
AS LANGUAGE JAVA
NAME 'POManager.enterOrder(int, int, java.lang.String,
java.lang.String, java.lang.String, java.lang.String,
java.lang.String, java.lang.String)';

PROCEDURE add_line_item (line_no NUMBER, order_no NUMBER,
stock_no NUMBER, quantity NUMBER, discount NUMBER)
AS LANGUAGE JAVA
NAME 'POManager.addLineItem(int, int, int, int, float)';

PROCEDURE total_orders
AS LANGUAGE JAVA
NAME 'POManager.totalOrders()';

PROCEDURE check_stock_item (stock_no NUMBER)
AS LANGUAGE JAVA
NAME 'POManager.checkStockItem(int)';

PROCEDURE change_quantity (new_qty NUMBER, order_no NUMBER,
stock_no NUMBER) AS LANGUAGE JAVA
NAME 'POManager.changeQuantity(int, int, int)';

PROCEDURE delete_order (order_no NUMBER)
AS LANGUAGE JAVA
NAME 'POManager.deleteOrder(int)';
END po_mgr;

Javaストアド・プロシージャのコール

Javaクラスを公開した後は、トップレベル、データベース・トリガー、SQLデータ操作言語(DML)文およびPL/SQLブロックから、Javaストアド・プロシージャをコールします。po_mgrパッケージ内のストアド・プロシージャを参照するには、ドット表記法を使用します。

無名PL/SQLブロックからは、次のように部品を保管することで、新しい発注書システムを開始できます。

BEGIN
po_mgr.add_stock_item(2010, 'camshaft', 245.00);
po_mgr.add_stock_item(2011, 'connecting rod', 122.50);
po_mgr.add_stock_item(2012, 'crankshaft', 388.25);
po_mgr.add_stock_item(2013, 'cylinder head', 201.75);
po_mgr.add_stock_item(2014, 'cylinder sleeve', 73.50);
po_mgr.add_stock_item(2015, 'engine bearning', 43.85);
po_mgr.add_stock_item(2016, 'flywheel', 155.00);
po_mgr.add_stock_item(2017, 'freeze plug', 17.95);
po_mgr.add_stock_item(2018, 'head gasket', 36.75);
po_mgr.add_stock_item(2019, 'lifter', 96.25);
po_mgr.add_stock_item(2020, 'oil pump', 207.95);
po_mgr.add_stock_item(2021, 'piston', 137.75);
po_mgr.add_stock_item(2022, 'piston ring', 21.35);
po_mgr.add_stock_item(2023, 'pushrod', 110.00);
po_mgr.add_stock_item(2024, 'rocker arm', 186.50);
po_mgr.add_stock_item(2025, 'valve', 68.50);
po_mgr.add_stock_item(2026, 'valve spring', 13.25);
po_mgr.add_stock_item(2027, 'water pump', 144.50);
COMMIT;
END;

次のように顧客を登録します。

BEGIN
po_mgr.add_customer(101, 'A-1 Automotive', '4490 Stevens Blvd',
'San Jose', 'CA', '95129', '408-555-1212');
po_mgr.add_customer(102, 'AutoQuest', '2032 America Ave',
'Hayward', 'CA', '94545', '510-555-1212');
po_mgr.add_customer(103, 'Bell Auto Supply', '305 Cheyenne Ave',
'Richardson', 'TX', '75080', '972-555-1212');
po_mgr.add_customer(104, 'CarTech Auto Parts', '910 LBJ Freeway',
'Dallas', 'TX', '75234', '214-555-1212');
COMMIT;
END;

次のように、様々な顧客による発注書を入力します。

BEGIN
po_mgr.enter_order(30501, 103, '14-SEP-1998', '21-SEP-1998',
'305 Cheyenne Ave', 'Richardson', 'TX', '75080');
po_mgr.add_line_item(01, 30501, 2011, 5, 0.02);
po_mgr.add_line_item(02, 30501, 2018, 25, 0.10);
po_mgr.add_line_item(03, 30501, 2026, 10, 0.05);

po_mgr.enter_order(30502, 102, '15-SEP-1998', '22-SEP-1998',
'2032 America Ave', 'Hayward', 'CA', '94545');
po_mgr.add_line_item(01, 30502, 2013, 1, 0.00);
po_mgr.add_line_item(02, 30502, 2014, 1, 0.00);

po_mgr.enter_order(30503, 104, '15-SEP-1998', '23-SEP-1998',
'910 LBJ Freeway', 'Dallas', 'TX', '75234');
po_mgr.add_line_item(01, 30503, 2020, 5, 0.02);
po_mgr.add_line_item(02, 30503, 2027, 5, 0.02);
po_mgr.add_line_item(03, 30503, 2021, 15, 0.05);
po_mgr.add_line_item(04, 30503, 2022, 15, 0.05);

po_mgr.enter_order(30504, 101, '16-SEP-1998', '23-SEP-1998',
'4490 Stevens Blvd', 'San Jose', 'CA', '95129');
po_mgr.add_line_item(01, 30504, 2025, 20, 0.10);
po_mgr.add_line_item(02, 30504, 2026, 20, 0.10);
COMMIT;
END;

出力をSQL*Plusテキスト・バッファにリダイレクトした後は、SQL*Plus内で次のようにtotalOrders()メソッドをコールできます。

SQL> SET SERVEROUTPUT ON
SQL> CALL dbms_java.set_output(2000);
...
SQL> CALL po_mgr.total_orders();
PONO   TOTAL
30501  1664
30502  275
30503  4149
30504  1635

Call completed.

9 Oracle Database Javaアプリケーションのパフォーマンス

Javaアプリケーションのパフォーマンスは、次の方法で向上させることができます。

- Oracle JVMのJust-In-Time(JIT)コンパイラ

- Javaのメモリー使用量

Oracle JVMのJust-In-Time(JIT)コンパイラ

この項では、Oracle Database 11gリリース1(11.1)以降で導入されているJust-In-Time(JIT)コンパイラについて説明します。この項の内容は、次のとおりです。

- Oracle JVMのJITの概要

- JITコンパイルの利点

- Oracle Database 11gで導入されたメソッド

注意:
以前のバージョンのOracle Databaseで使用されていたコンパイラが、JITコンパイラに切り替えられています。

Oracle JVM JITの概要

Oracle 11gリリース1(11.1)以降には、Oracle JVM環境用のJust-In-Time(JIT)コンパイラがあります。Oracle JVM用のJITコンパイラでは、外部のメカニズムを使用せずにコードの無効化、再コンパイルおよび格納を管理するため、実行速度が上がります。このコンパイラは、動的に収集されたプロファイル・データに基づき、ネイティブのマシン・コードをコンパイルするためにJavaメソッドを透過的に選択し、Javaセッションの実行でこれらのメソッドを動的に使用できるようにします。さらに、Oracle JVMのクラスの解決モデルを利用して、データベースのコール、セッションまたはインスタンス間でコンパイル済Javaメソッドをオプションで存続できるようにします。Javaコードのセマンティクスが変わらないと判断される場合、このように存続させることで、セッションまたはインスタンス間の不要な再コンパイルのオーバーヘッドが回避されます。

JITコンパイラは、java_jit_enabledと呼ばれるブール値の新しい初期化パラメータで制御します。java_jit_enabledパラメータの値をtrueに指定して使用頻度の高いJavaメソッドを実行する場合、そのJavaメソッドはJITコンパイラによってネイティブ・コードに自動的にコンパイルされ、インスタンスのすべてのセッションで使用できるようになります。また、java_jit_enabledパラメータをtrueに設定すると、JITコンパイルが中止し、すでにコンパイルしたメソッドを解析に戻します。VMは、包含Javaクラスの次の再解決のように、必要に応じてJavaメソッドのネイティブ・コードを自動的に再コンパイルします。

注意:
Linuxの場合、Oracle JVM JITではPOSIX共有メモリーが使用され、これには/dev/shmディレクトリへのアクセスが必要です。/dev/shmディレクトリのタイプはtmpfsである必要があり、次のようにしてこのディレクトリをマウントする必要があります。

- rw許可およびexecute許可を設定

- noexecもnosuidも設定しない

適切なマウント・オプションを使用しない場合、データベースのインストール時に次の障害が発生する可能性があります。

ORA-29516: Aurora assertion failure: Assertion failure at joez.c:
Bulk load of method java/lang/Object.<init> failed; insufficient shm-object space

JITコンパイラは、インスタンスの1つのバックグラウンド・プロセスでMMONスレーブとして実行されます。そのため、JITコンパイラが実行中で、メソッドをアクティブにコンパイルしている間には、このCPUとメモリー・リソースを消費するバックグラウンド・プロセスが、アクティブなユーザーJavaセッションと同じになることがあります。

JITコンパイルの利点

次に、以前のバージョンのOracleデータベースで使用されるコンパイル方法よりも優れたJITコンパイルの利点を示します。

- JITコンパイルは、透過的に動作します。

- JITコンパイルは、Javaクラスのパフォーマンスを高速化します。

- Javaコードのセマンティクスが変わらないと判断される場合、JITが格納したコンパイル済コードにより、セッションまたはインスタンス間のJavaプログラムの再コンパイルが回避されます。

- JITコンパイルは、Cコンパイラが不要です。

- JITコンパイルは、一部の配列境界チェックを行いません。

- JITコンパイルは、ブロック内の共通副次式を除去します。

- JITコンパイルは、空のメソッドを除去します。

- JITコンパイルは、ローカル変数の割当てを登録するための領域を定義します。

- JITコンパイルは、フロー分析の必要がありません。

- JITコンパイルは、インライン・コードを制限します。

Oracle Database 11gで導入されたメソッド

11gリリース1 (11.1)以降では、DBMS_JAVAパッケージが次の新しいpublicメソッドによって拡張され、同期メソッドのコンパイルを制御し、解析したメソッドの実行に戻すためのJavaエントリ・ポイントが提供されます。

set_native_compiler_option

このプロシージャは、ネイティブ・コンパイラのオプションを現行スキーマの指定の値に設定します。optionNameで指定したオプションで値の重複が許可されない場合、この値は無視されます。

PROCEDURE set_native_compiler_option(optionName VARCHAR2,
value VARCHAR2);

unset_native_compiler_option

このプロシージャは、現行スキーマについて、ネイティブ・コンパイラのオプション/値のペアの設定を解除します。optionNameで指定したオプションで値の重複が許可されない場合、この値は無視されます。

PROCEDURE unset_native_compiler_option(optionName VARCHAR2,
value VARCHAR2);

compile_class

このファンクションは、現行スキーマのclassnameで特定されるクラスで定義されたすべてのメソッドをコンパイルします。コンパイルが成功したメソッドの数を戻します。クラスが存在しない場合、ORA-29532 (捕捉されないJava例外)が発生します。

FUNCTION compile_class(classname VARCHAR2) return NUMBER;

uncompile_class

このファンクションは、現行スキーマのclassnameで特定されるクラスで定義されたすべてのメソッドをアンコンパイルします。アンコンパイルが成功したメソッドの数を戻します。引数permanentpの値がゼロ以外の場合、これらのメソッドを動的アンコンパイルが永久に可能であるものとしてマークします。それ以外は、今後の動的な再コンパイルの対象となります。クラスが存在しない場合、ORA-29532 (捕捉されないJava例外)が発生します。

FUNCTION uncompile_class(classname VARCHAR2,
permanentp NUMBER default 0) return NUMBER;

compile_method

このファンクションは、現行スキーマのclassnameで特定されるクラスで定義されたnameおよびJava typeシグネチャで指定したメソッドをコンパイルします。コンパイルが成功したメソッドの数を戻します。クラスが存在しない場合、ORA-29532 (捕捉されないJava例外)が発生します。

FUNCTION compile_method(classname  VARCHAR2,
methodname VARCHAR2,
methodsig  VARCHAR2) return NUMBER;

uncompile_method

このファンクションは、現行スキーマのclassnameで特定されるクラスで定義されたnameおよびJava typeシグネチャで指定したメソッドをアンコンパイルします。アンコンパイルが成功したメソッドの数を戻します。引数permanentpの値がゼロ以外の場合、メソッドを動的アンコンパイルが永久に可能であるものとしてマークします。それ以外は、今後の動的な再コンパイルの対象となります。クラスが存在しない場合、ORA-29532 (捕捉されないJava例外)が発生します。

FUNCTION uncompile_method(classname  VARCHAR2,
methodname VARCHAR2,
methodsig  VARCHAR2,
permanentp NUMBER default 0) return NUMBER;

Javaのメモリー使用量

標準およびカスタムのデータベース・インストール・プロセスでは、開発時に標準的なJava使用のために構成されているデータベースが提供されます。ただし、Javaの実行時の使用量は、デプロイされたアプリケーションのシステム・リソースの使用率によって決まります。開発時に使用するリソース率は、実行するアクティビティによって大きく異なる場合があります。次の各項では、メモリーの構成方法、システム・グローバル領域(SGA)メモリーの使用量を調べる方法、およびJavaが使用するメモリーの問題を示すエラーについて説明します。

- メモリー初期化パラメータの構成

- Javaプール・メモリー

- Javaプール・メモリー使用量の表示

- メモリー不足エラーの修正

- Javaコールおよびセッション・ヒープ統計情報の表示

メモリー初期化パラメータの構成

次のデータベース初期化パラメータを変更して、アプリケーションに必要なメモリー使用量がより正確に反映されるようにメモリー使用量をチューニングできます。

- SHARED_POOL_SIZE
共有プール・メモリーはJVM内のクラス・ローダーによって使用されます。クラス・ローダーは、クラスをロードするたびに平均約8KBのメモリーを使用します。共有プール・メモリーは、データベースにクラスをロードして解決するときに使用されます。また、データベース内でソースをコンパイルする場合やデータベースでJavaリソース・オブジェクトを使用する場合にも使用されます。

SHARED_POOL_SIZEで指定したメモリーは、loadjavaツールの使用時に一時的に消費されます。データベース初期化プロセスでは、約8,000クラスのJavaバイナリをロードして解決するため、SHARED_POOL_SIZEを96MBに設定する必要があります。コール仕様を作成するとき、および実行時に動的にロードされたJavaクラスをシステムで追跡するときも、SHARED_POOL_SIZEリソースが消費されます。

- JAVA_POOL_SIZE
Oracle JVMメモリー・マネージャでは、主にJavaメソッドとクラス定義のインメモリー表現と、共有サーバー・モードでコール終了時にセッション領域に移行した静的Javaの状態のためにJAVA_POOL_SIZEを使用します。前者の場合は、メモリー・コストをすべてのJavaユーザー間で分担します。後者の場合は、各セッションの静的変数で保持する実際の状態数に基づいて、JAVA_POOL_SIZEの値が変わります。ただし、最小値を50MBにすることをお薦めします。

- JAVA_SOFT_SESSIONSPACE_LIMIT
このパラメータを使用すると、1つのセッションにおけるJavaのメモリー使用量に弱い制限を指定でき、Javaのメモリー制限を増やす必要がある場合は警告を表示できます。メモリーが割り当てられるたびに、割り当てられたメモリーの合計量がこの制限に対してチェックされます。

ユーザーのセッション中にJavaの状態がこのサイズを超えると、Oracle JVMが警告を生成し、トレース・ファイルに書き込みます。この警告は情報用のメッセージでアプリケーションに影響を与えませんが、デプロイするクラスのメモリー要件、特にセッション領域の使用量に関する要件を把握して管理する必要があります。

注意:
このパラメータは共有サーバー環境にのみ適用できます。

- JAVA_MAX_SESSIONSPACE_SIZE
ユーザーがコール可能でサーバー上で実行されているJavaプログラムを、メモリー使用量を制限しない方法で実行できる場合は、このパラメータを使用して、使用可能なセッション領域に対して強い制限を設定できます。デフォルトは4GBです。この上限は、通常到達することのない高い値に設定します。

ユーザーのセッション中のJavaの状態がこのサイズを超えそうになると、メモリー不足障害が発生します。

注意:
このパラメータは共有サーバー環境にのみ適用できます。

データベース・テンプレート内のプール・サイズの初期化

データベースのインストール・テンプレートのJAVA_POOL_SIZEおよびSHARED_POOL_SIZEに対して、デフォルト値を設定できます。

図9-1に示すように、これらの値は、Database Configuration Assistantの「メモリー」セクションで変更できます。

図9-1 Oracle JVMのメモリー・パラメータの構成

Javaプール・メモリー

Javaプール・メモリーはSGAのサブセットで、ページワイズに調整する必要があるメモリー用にJavaによって排他的に使用されます。大部分はこのように使用されますが、Javaクラスの共有定義にメモリーのすべてが使用されるわけではありません。Javaプール・メモリーの他の使用方法は、Oracle Databaseサーバーの実行モードによって異なります。

専用サーバーで使用されるJavaプール・メモリー

次に、専用サーバーで使用されるJavaプール・メモリーの構成を示します。

- 使用される各Javaクラスのほとんどの共有部分。
これには、コード・ベクトルやメソッドなどの読取り専用メモリーが含まれます。合計すると、各クラスについて約4KBから8KBになります。

- 各セッションのセッション当たりのJavaの状態は使用されません。
専用サーバーの場合、これはSGAではなく、プログラム・グローバル領域(PGA)内のユーザー・グローバル領域(UGA)に格納されます。

専用サーバーでは、必要なJavaプール・メモリー合計は実行するアプリケーションによって異なり、通常、10から50MB程度になります。

共有サーバーで使用されるJavaプール・メモリー

共有サーバーで使用されるJavaプール・メモリーの構成を次に示します。

- 使用される各Javaクラスのほとんどの共有部分
これには、ベクトルやメソッドなどの読取り専用メモリーが含まれます。合計すると、このメモリーは通常、各クラスについて約4KBから8KBになります。

- 各セッション・メモリーに対するUGAの一部
特に、データベースのコール間で使用中になっているオブジェクトのメモリーは、常にJavaプールから割り当てられます。

Javaプール・メモリーのサイズは制限されているため、アプリケーションで必要なメモリー量を見積り、アプリケーションで作成する同時実行セッション数を乗じて、必要なJavaプール・メモリーの総量を計算する必要があります。各UGAは必要に応じて拡大または縮小できます。ただし、UGA全体が一定のJavaプール領域に収まるようにしてください。

共有サーバーでは、Javaプールは非常に大きくなる場合があります。Java集中型のマルチ・ユーザー・アプリケーションでは、100MB以上が必要になる場合があります。

注意:
クライアントでコードをコンパイルしてからサーバーにロードするのではなく、サーバー上でコードをコンパイルする場合は、JAVA_POOL_SIZEをデフォルトの20MBより大きいサイズに設定する必要がある場合があります。

Java対応セッションの数の削減

データベース内のJavaのトップレベルの起動は、クライアント側のアプリケーションまたはユーティリティによって発行されます。各クライアントに専用サーバーがある場合、大規模なデプロイメントを行うと、データベース・サーバーでリソースが大量に消費され、リソースの浪費につながります。クライアント側の接続プールまたはデータベース常駐接続プール(DRCP)を使用すると、データベース・プロセスおよびセッションの数を削減できます。

関連項目:
DRCPの詳細は、『Oracle Database JDBC開発者ガイド』を参照してください。

Javaプール・メモリー使用量の表示

V$SGASTAT表を表示すると、Javaプール・メモリーの使用量を調べることができます。この表の行には、プール、名前およびバイト数が表示されます。特に、最後の2行にはJavaプール・メモリーの使用量と空き容量が表示されます。この2行の数字の合計値は、データベース初期化ファイルに設定したバイト数と等しくなります。

SVRMGR> select * from v$sgastat;

POOL        NAME                            BYTES
----------- -------------------------- ----------
fixed_sga                       69424
db_block_buffers              2048000
log_buffer                     524288
shared pool free memory                  22887532
shared pool miscellaneous                  559420
shared pool character set object            64080
shared pool State objects                   98504
shared pool message pool freequeue         231152
shared pool PL/SQL DIANA                  2275264
shared pool db_files                        72496
shared pool session heap                    59492
shared pool joxlod: init P                   7108
shared pool PLS non-lib hp                   2096
shared pool joxlod: in ehe                4367524
shared pool VIRTUAL CIRCUITS               162576
shared pool joxlod: in phe                2726452
shared pool long op statistics array        44000
shared pool table definiti                    160
shared pool KGK heap                         4372
shared pool table columns                  148336
shared pool db_block_hash_buckets           48792
shared pool dictionary cache              1948756
shared pool fixed allocation callback         320
shared pool SYSTEM PARAMETERS               63392
shared pool joxlod: init s                   7020
shared pool KQLS heap                     1570992
shared pool library cache                 6201988
shared pool trigger inform                  32876
shared pool sql area                      7015432
shared pool sessions                       211200
shared pool KGFF heap                        1320
shared pool joxs heap init                   4248
shared pool PL/SQL MPCODE                  405388
shared pool event statistics per sess      339200
shared pool db_block_buffers               136000
java pool   free memory                  30261248
java pool   memory in use                19742720
37 rows selected.

メモリー不足エラーの修正

クラスのロード中にメモリー不足になると、エラーが何も表示されずにロードが失敗し、データベースに無効なクラスが残されます。無効なクラスをコールまたは解決しようとすると、実行時にClassNotFoundExceptionインスタンスまたはNoClassDefFoundExceptionインスタンスがスローされます。破損したクラス・ファイルをロードしようとした場合も同じ例外が発生します。この場合には次の処置を実行してください。

- サーバーにロードするセットに、実際にクラスが含まれていることを検証します。

- loadjava -forceオプションを使用して、新しいクラスをロードすることによって、サーバーにすでに常駐しているクラスを強制的に置き換えます。

- loadjava -resolveオプションを使用して、ロード・プロセス時にクラスの解決を試みます。これによって、実行時ではなくロード時に、欠落しているクラスを捕捉できます。

- 新しくロードされたクラスの状態を再確認するために、そのクラスが含まれているスキーマのデータベースに接続して、次のように実行します。

SELECT * FROM user_objects WHERE object_name = dbms_java.shortname('');

STATUSフィールドにVALIDと表示されていることを確認してください。loadjavaツールからメモリーの問題や接続を失うなどの障害が発生した場合は、SHARED_POOL_SIZEおよびJAVA_POOL_SIZEを増やして再試行してください。

Javaコールおよびセッション・ヒープ統計情報の表示

データベース・パフォーマンス・ビューv$sesstatは、多数のJavaメモリー使用量統計情報を記録します。この統計情報は、Javaコール中に頻繁に更新されます。次の例は、SIDが102のデータベース・セッションのJavaコールの戻り値とセッション・ヒープ統計情報を示します。

SQL> select s.sid, n.name p_name, st.value from v$session s, v$sesstat st, v$statname n where s.sid=102
and s.sid=st.sid and n.statistic# = st.statistic# and n.name like 'java%';

SID P_NAME                                        VALUE
---------- ---------------------------------------- ----------
102 java call heap total size                   6815744
102 java call heap total size max               6815744
102 java call heap used size                     668904
102 java call heap used size max                 846920
102 java call heap live size                     667112
102 java call heap live size max                 704312
102 java call heap object count                   13959
102 java call heap object count max               17173
102 java call heap live object count              13907
102 java call heap live object count max          14916
102 java call heap gc count                      432433
102 java call heap collected count            123196423
102 java call heap collected bytes           5425972216
102 java session heap used size                  444416
102 java session heap used size max              444416
102 java session heap live size                  444416
102 java session heap live size max              444416
102 java session heap object count                    0
102 java session heap object count max                0
102 java session heap live object count               0
102 java session heap live object count max           0
102 java session heap gc count                        0
102 java session heap collected count                 0
102 java session heap collected bytes                 0

24 rows selected.

10 Oracle Database Javaアプリケーションのセキュリティ

セキュリティの範囲は広く、接続に関するネットワーク・セキュリティ、オペレーティング・システム・リソースまたはJava仮想マシン(JVM)定義クラスやユーザー定義クラスのアクセス制御および実行制御などがあります。また、外部ソースからインポートされたJavaアーカイブ(JAR)ファイルのバイトコードの検証も含まれます。次の各項では、Oracle DatabaseのJavaアプリケーションに使用できる様々なセキュリティ・サポートについて説明します。

- ネットワーク接続のセキュリティ

- データベース・コンテンツとOracle JVMセキュリティ

- データベース認証のメカニズム

- Oracle DatabaseでのRuntime.exec機能のセキュアな使用

ネットワーク接続のセキュリティ

ネットワーク・セキュリティには、認証およびデータの機密保護という2つの主要な側面があります。認証およびデータの機密保護のタイプは、データベースにOracle Netを介して接続するか、またはJava Database Connectivity(JDBC)を介して接続するかによって決定します。次の表で、Oracle NetおよびJDBC接続のセキュリティについて説明します。

接続のセキュリティ

説明

Oracle Net

データベースでは、ユーザーによるデータベースへの接続を許可する前に、そのユーザーの認証と認可の両方を要求できます。Oracle Netデータベース接続のセキュリティでは、次の条件を1つ以上満たす必要があります。

- クライアント検証用のユーザー名とパスワード。各接続要求ごとに、Oracle Netに構成されたユーザー名とパスワードを入力する必要があります。

- 暗号化、KerberosまたはSecureID用のAdvanced Networking Option。

- 証明書認証用のSSL。

JDBC

JDBC接続に求められるセキュリティは、Oracle Netデータベース接続に求められる制約と同じです。

関連項目:

- 『Oracle Database Net Services管理者ガイド』

- 『Oracle Databaseセキュリティ・ガイド』

- 『Oracle Database JDBC開発者ガイド』

データベース・コンテンツとOracle JVMセキュリティ

データベースに接続した後も、データベースに格納されたリソースにアクセスするには、適切なJava 2セキュリティの許可とデータベース権限が必要になります。次のようなリソースがあります。

- 表やPL/SQLパッケージなどのデータベース・リソース

- ファイルやソケットなどのオペレーティング・システム・リソース

- Oracle JVMクラス

- ユーザーによってロードされたクラス

これらのリソースは次の方式で保護されます。

リソース・セキュリティ

説明

データベース・リソース・セキュリティ

データベース・リソースに対する認可では、リソースに対してデータベース権限(Java 2セキュリティの許可とは異なります)を付与する必要があります。たとえば、データベース・リソースには表、クラスおよびPL/SQLパッケージが含まれます。
すべてのユーザー定義クラスは、他のスキーマのユーザーから保護されます。loadjavaツールのオプションを使用して、他のユーザーまたはスキーマに対して実行権限を付与できます。

JVMセキュリティ

Oracle JVMでは、オペレーティング・システム・リソースを保護するためにPermissionオブジェクトを使用するJava 2セキュリティが使用されます。Java 2セキュリティは、起動時に自動的にインストールされ、すべてのオペレーティング・システム・リソースとOracle JVMクラスをJAVA_ADMIN以外のすべてのユーザーから保護します。JAVA_ADMINユーザーは他のユーザーに、これらのクラスにアクセスするパーミッションを付与できます。

注意:

- Oracle JVMは、出荷時の状態では、JDK1.5およびJDK 6に含まれる制限付きの強い暗号化を使用しています。アプリケーションで無制限強度の暗号化を使用するには、適切なバージョン固有のファイルを次のWebサイトからダウンロードし、インストールする必要する必要があります。
http://www.oracle.com/technetwork/indexes/downloads/index.html

- 権限の付与または取消しに使用されるOracle JVMクラスは、サーバー上でのみ実行できます。

この項の内容は、次のとおりです。

- Java 2セキュリティ

- パーミッションの設定

- デバッグのパーミッション

- クラスをロードするためのパーミッション

- デフォルトのjava.securityリソースのカスタマイズ

関連項目:

- 『Oracle Database開発ガイド』

- 第12章「スキーマ・オブジェクトおよびOracle JVMユーティリティ」

Java 2セキュリティ

各ユーザーまたはスキーマには、ソケット、ファイルおよびシステム・プロパティなどのオペレーティング・システム・リソースにアクセスするための適切なパーミッションを割り当てる必要があります。

Java 2セキュリティは、Javaアプリケーションに柔軟で構成可能なセキュリティを提供します。Java 2セキュリティでは、ロードされた各オブジェクトについてスキーマまたはロールに付与する許可を正確に定義できます。Oracle8i リリース8.1.5では、次の保護ロールを使用できます。

- JAVAUSERPRIV
プロパティの検査を含むいくつかのパーミッション

- JAVASYSPRIV
Oracle JVMの保護パッケージの更新を含む主要なパーミッション

注意:
このリリースでは下位互換性を維持するために前述の2つのロールが残されています。しかし、これらは使用せずに、各パーミッションを明示的に指定することをお薦めします。

Oracle JVMセキュリティはJava 2セキュリティに基づいているため、クラスに対する許可はクラス単位で割り当てます。これらのパーミッションは、データベース管理ツールを使用して割り当てられます。各パーミッションは、Permissionオブジェクトにカプセル化され、Permission表に格納されます。Permissionには、String値を取る、target属性とaction属性が含まれます。

Java 2セキュリティはデータベースを対象に作成されていません。Java 2セキュリティ・モデルをデータベース内で適用すると、いくつかの相違が明らかになります。たとえば、Java 2セキュリティでは、すべてのアプレットは暗黙的に信頼がおけないと定義され、CLASSPATH内のクラスはすべて信頼できると定義されます。Oracle Databaseでは、すべてのクラスがセキュアなデータベースにロードされます。このため、信頼できるクラスとして処理されません。

次の表で、標準のJava 2セキュリティとOracle Databaseのセキュリティ実装の違いを説明します。

Java 2セキュリティ標準

Oracle Databaseのセキュリティ実装

CLASSPATHに格納されたJavaクラスは信頼できます。

Javaクラスはすべてデータベース内にロードされます。複数のクラスは、付与されたパーミッションに基づいて、クラスごとに信頼されます。

javaコマンドの-usepolicyフラグを使用してポリシーを指定できます。

ポリシーはPolicyTableに指定する必要があります。

独自にSecurityManagerを作成するか、またはLauncherを使用できます。

独自にSecurityManagerを作成できます。ただし、Oracle DatabaseのSecurityManagerのみを使用するか、またはそれを拡張することをお薦めします。動作を変更する場合は、SecurityManagerを定義しないでください。かわりに、oracle.aurora.rdbms. SecurityManagerImplを拡張して特定のメソッドをオーバーライドしてください。

SecurityManagerはデフォルトでは初期化されません。SecurityManagerは手動で初期化する必要があります。

Oracle JVMは、起動時に常にSecurityManagerを初期化します。

パーミッションは、アプリケーションまたはアプレットのロード先(URL)またはキーコード(符号付きコード)によって決まります。

パーミッションは、クラスのロード先のスキーマによって決まります。Oracle Databaseは、符号付きコードをサポートしていません。

セキュリティ・ポリシーはファイルに定義されます。

PolicyTable定義はセキュアなデータベース表に保持されます。

セキュリティ・ポリシー・ファイルは、適切なパーミッションがある場合、テキスト・エディタまたはツールを使用して更新できます。

PolicyTableは、DBMS_JAVAプロシージャを使用して更新できます。初期化後、JAVA_ADMINのみがPolicyTableを変更するパーミッションを保持します。他のユーザーにパーミッションを付与できるように、JAVA_ADMINからPolicyTableを変更する権限を付与される必要があります。

パーミッションは保護ドメインに割り当てられます。クラスはこの保護ドメインに属すことができます。

同じスキーマ内のすべてのクラスは同じ保護ドメイン内に存在します。

コードの識別には、CodeSourceクラスを使用できます。

- URLと証明書が等しい場合、equals()メソッドはtrueを戻します。

- 最初のCodeSourceが特定のCodeSourceオブジェクトを含む汎用表記の場合、implies()メソッドはtrueを戻します。

スキーマの識別には、CodeSourceクラスを使用できます。

- スキーマが同じ場合、equals()メソッドはtrueを戻します。

- スキーマが同じ場合、implies()メソッドはtrueを戻します。

正(grant)のパーミッションのみサポートします。

正(grant)および制限(restrict)の両方のパーミッションをサポートします。

パーミッションの設定

Java 2セキュリティと同様に、Oracle Databaseはセキュリティ・クラスをサポートしています。通常は、ツールを使用するか、またはセキュリティ・ポリシー・ファイルを編集して、コード・ベースにパーミッションを設定します。Oracle Databaseでは、データベースのポリシー表を変更するDBMS_JAVAプロシージャを使用して、パーミッションを動的に設定します。

ポリシー表を表示するために、USER_JAVA_POLICYとDBA_JAVA_POLICYの2つのビューが用意されています。いずれのビューにも、付与されているパーミッションと制限パーミッションに関する情報が含まれています。DBA_JAVA_POLICYビューにはポリシー表内のすべての行が表示されます。USER_JAVA_POLICYビューには現行ユーザーに関連するパーミッションのみが表示されます。次に、各ビューに表示される行について説明します。

表の列

説明

Kind(種類)

GRANTまたはRESTRICT。このパーミッションが正または制限のどちらであるかが表示されます。

Grantee(権限受領者)

Permissionオブジェクトが割り当てられたユーザー、スキーマまたはロールの名前。

Permission_schema(パーミッションのスキーマ)

Permissionオブジェクトのロード先スキーマ。

Permission_type(パーミッション・タイプ)

java.io.FilePermissionなど、完全なクラス名を含む文字列によって指定されたPermissionクラス・タイプ。

Permission_name(パーミッション名)

Permissionオブジェクトのtarget属性。パーミッションを定義するときにこの名前を使用します。PolicyTablePermissionタイプのPermissionオブジェクトのターゲットを定義すると、名前が複雑になる場合があります。
関連項目: 「ポリシー表を更新するための管理パーミッションの取得」

Permission_action(パーミッションのアクション)

Permissionオブジェクトのaction属性。多くのパーミッションでは、そのパーミッションに対して適切なアクションがない場合、NULL値と想定されます。

状態(STATUS)

ENABLEDおよびDISABLED。Permissionオブジェクトの行を作成した後は、その行を使用禁止にしたり、再び使用可能にできます。この列には、パーミッションが使用可能または使用禁止のどちらであるかが表示されます。

Key(キー)

この行を識別するために使用する順序番号。パーミッションを使用禁止、使用可能または削除するときにこの番号を指定します。

パーミッションを設定するには、次の2つの方法があります。

- 各パーミッションのファイングレイン定義

- ロールに割り当てられる一般的なパーミッション定義

注意:
完全なセキュリティ設定を確保するには、ファイングレイン定義を実装してください。一般的な定義の方が実装は簡単ですが、必要なレベルのセキュリティ設定を得られない場合があります。

各パーミッションのファイングレイン定義

ファイングレイン定義を使用して、特定のユーザーまたはロールに対してパーミッションを個別に付与できます。アクセスするためのパーミッションを付与しないと、そのスキーマでのアクセスは拒否されます。ポリシー表に個別にパーミッションを設定するには、次の情報を指定する必要があります。

パラメータ

説明

Grantee(権限受領者)

権限を適用するユーザー、スキーマまたはロールの名前。PUBLICに指定すると、その行がすべてのユーザーに適用されます。

Permission type(パーミッション・タイプ)

パーミッションの付与対象となるPermissionクラス。たとえば、あるファイルへのアクセスを定義する場合、パーミッション・タイプはFilePermissionになります。このパラメータには、java.lang.security.Permissionを拡張するクラスの完全修飾名を指定します。クラスがSYSに入っていない場合は、クラス名に接頭辞schema:を付ける必要があります。たとえば、mySchema:myPackage.MyPermissionは、ユーザー生成のパーミッションの有効な名前です。

Permission name(パーミッション名)

Permissionクラスによって定義されたターゲット属性の意味。適切なPermissionクラスで関連する名前を調べてください。

Permission action(パーミッションのアクション)

指定できるアクションのタイプ。パーミッション・タイプによって異なります。たとえば、FilePermissionには、読取りまたは書込みのアクションを指定できます。

Key(キー)

パーミッションを付与または制限すると戻される番号で、enable、disableまたはdeleteの各メソッドに使用します。

パーミッションは、SQLまたはJavaのいずれかを使用して付与できます。いずれの場合もパーミッション表内の行を識別する行キー識別子が戻されます。DBMS_JAVAのJavaバージョンでは、各メソッドによって、行キー識別子が戻りパラメータまたはパラメータ・リストのOUT変数として戻されます。PL/SQLのDBMS_JAVAパッケージでは、行キーはkey OUTパラメータを定義するプロシージャでのみ戻されます。このキーを使用して、特定のパーミッションを使用可能または使用禁止にします。

権限付与を実行した後、該当のパーミッション用に行がすでに存在している場合、更新は発生しませんが、その行のキーが戻されます。行が使用禁止になっている場合は、権限付与を実行すると既存の行が使用可能になります。

注意:
FilePermissionを付与する場合は、/private/oracleのように、ディレクトリまたはファイルの物理的な名前を指定する必要があります。$ORACLE_HOMEなどの環境変数、またはシンボリック・リンクは指定できません。ディレクトリ内のすべてのファイルを示すには、次のように「*」記号を指定します。

/private/oracle/*

ディレクトリ内のすべてのディレクトリとファイルを示すには、次のように「-」記号を指定します。

/private/oracle/-

DBMS_JAVAパッケージを使用してパーミッションを付与するには、次のように記述します。

procedure grant_permission ( grantee varchar2, permission_type varchar2, permission_name varchar2,
permission_action varchar2 )

procedure grant_permission ( grantee varchar2, permission_type varchar2, permission_name varchar2,
permission_action varchar2, key OUT number)

Javaを使用してパーミッションを付与するには、次のように記述します。

long oracle.aurora.rdbms.security.PolicyTableManager.grant ( java.lang.String grantee,
java.lang.String permission_type, java.lang.String permission_name, java.lang.String permission_action);

void oracle.aurora.rdbms.security.PolicyTableManager.grant ( java.lang.String grantee,
java.lang.String permission_type, java.lang.String permission_name, java.lang.String permission_action, long[] key);

DBMS_JAVAパッケージを使用してパーミッションを制限するには、次のように記述します。

procedure restrict_permission ( grantee varchar2, permission_type varchar2, permission_name varchar2,
permission_action varchar2)

procedure restrict_permission ( grantee varchar2, permission_type varchar2, permission_name varchar2,
permission_action varchar2, key OUT number)

Javaを使用してパーミッションを制限するには、次のように記述します。

long oracle.aurora.rdbms.security.PolicyTableManager.restrict ( java.lang.String grantee,
java.lang.String permission_type, java.lang.String permission_name, java.lang.String permission_action);

void oracle.aurora.rdbms.security.PolicyTableManager.restrict ( java.lang.String grantee,
java.lang.String permission_type, java.lang.String permission_name, java.lang.String permission_action, long[] key);

例10-1に、grant_permission()メソッドを使用してパーミッションを付与する方法を示します。例10-2に、restrict()メソッドを使用してパーミッションを制限する方法を示します。

例10-1 パーミッションの付与

ポリシー表を変更するための適切なパーミッションがあることを前提とすると、DBMS_JAVAパッケージ内にあるgrant_permission()メソッドを使用してPolicyTableを変更し、指定ファイルへのユーザー・アクセスを許可できます。この例のユーザーLarryは、PolicyTableを変更するパーミッションを持っています。SQLパッケージ内で、Larryは、次のように、ユーザーDaveに対してファイルの読取り/書込みのパーミッションを付与できます。

connect larry
Enter password: password

REM Grant DAVE permission to read and write the Test1 file.
call dbms_java.grant_permission('DAVE', 'java.io.FilePermission', '/test/Test1',  'read,write');

REM commit the changes to PolicyTable
commit;

例10-2 パーミッションの制限

一般的な規則に対する制限または例外を指定するには、restrict()メソッドを使用できます。一般的な規則とは、ほとんどの場合、パーミッションがtrueの状態(付与されている)の規則を指します。ただし、この規則には例外がある場合があります。この例外に対して、制限パーミッションを指定します。

ディレクトリ全体に対して読取りまたは書込みを禁止する一般的な規則を定義してある場合は、restrict()メソッドを使用してこの規則の一部を制限するように定義できます。たとえば、/tmpディレクトリに格納されている自分のパスワード・ファイルを除いて、このディレクトリ内のすべてのファイルへのアクセスを許可するには、/tmpディレクトリ内のすべてのファイルに対する読取り/書込みのパーミッションを付与した後、パスワード・ファイルに対する読取り/書込みアクセスを制限します。

制限に対する例外を指定する場合は、明示的な権限付与パーミッションを作成して制限パーミッションをオーバーライドする必要があります。前述の例では、ファイルの所有者がパスワードファイルを変更できるようにするには、1人のユーザーに対して、アクセスを許可するためのさらに明示的なパーミッションを付与することによって、制限をオーバーライドできます。Oracle JVMセキュリティではすべての規則を考慮して、パスワード・ファイルへのアクセス権を持つユーザーを判断します。次の図にこれを示します。

明示的な規則は次のとおりです。

制限パーミッションに暗黙的な要求が含まれている場合に、付与パーミッションを有効にするには、その制限パーミッションにも暗黙的な付与が含まれている必要があります。

次に、この例を実装するコードを示します。

connect larry
Enter password: password

REM Grant permission to all users (PUBLIC) to be able to read and write
REM all files in /tmp.
call dbms_java.grant_permission('PUBLIC', 'java.io.FilePermission', '/tmp/*', 'read,write');

REM Limit permission to all users (PUBLIC) from reading or writing the
REM password file in /tmp.
call dbms_java.restrict_permission('PUBLIC', 'java.io.FilePermission', '/tmp/password', 'read,write');

REM By providing a more specific rule that overrides the limitation,
REM Larry can read and write /tmp/password.
call dbms_java.grant_permission('LARRY', 'java.io.FilePermission', '/tmp/password', 'read,write');

commit;

このコードでは、次の処理が実行されます。

1. すべてのユーザーに、/tmp内のすべてのファイルに対する読取り/書込みのパーミッションを付与します。

2. すべてのユーザーについて、/tmp内のpasswordファイルに対する読取り/書込みを制限します。

3. Larryにpasswordファイルに対する読取り/書込みの明示的なパーミッションを付与します。

ポリシー表を更新するための管理パーミッションの取得

すべてのパーミッションはPolicyTable内の行です。ポリシー表はデータベース内の表であるため、変更には適切なパーミッションが必要です。特に、PolicyTablePermissionオブジェクトは表を変更するために必要です。Oracle JVMを初期化した後、PolicyTablePermissionを付与されたJAVA_ADMINロールのみがPolicyTableを変更できます。データベース管理者(DBA)にはただちにJAVA_ADMINロールが割り当てられます。したがって、DBAグループに割り当てられているユーザーは、JAVA_ADMINの全パーミッションを自動的に取得できます。

この表にパーミッションを行として追加する必要がある場合は、JAVA_ADMINによって、PolicyTablePermissionを使用してスキーマに更新権限が付与されている必要があります。このパーミッションは、スキーマが表に行を追加できるように定義します。各PolicyTablePermissionは、特定のパーミッション・タイプに対応しています。たとえば、あるファイルへのアクセスを制御するパーミッションを追加するには、FilePermissionに対するパーミッションを付与または制限できるPolicyTablePermissionが必要です。一度これを実行すると、FilePermissionに対する管理パーミッションを持つことができます。

管理者は、他のパーミッションと同様の方法でPolicyTablePermissionを付与または制限できますが、構文は複雑になります。使いやすくするため、grant_policy_permission()またはgrantPolicyPermission()メソッドを使用して、管理パーミッションを付与できます。

DBMS_JAVAを使用してポリシー表の管理パーミッションを付与するには、次のように記述します。

procedure grant_policy_permission ( grantee varchar2, permission_schema varchar2,
permission_type varchar2, permission_name varchar2 )

procedure grant_policy_permission ( grantee varchar2, permission_schema varchar2,
permission_type varchar2, permission_name varchar2, key OUT number )

Javaを使用してポリシー表の管理パーミッションを付与するには、次のように記述します。

long oracle.aurora.rdbms.security.PolicyTableManager.grantPolicyPermission (java.lang.String grantee, java.lang.String permission_schema,
java.lang.String permission_type, java.lang.String permission_name);

void oracle.aurora.rdbms.security.PolicyTableManager.grantPolicyPermission (java.lang.String grantee, java.lang.String permission_schema,
java.lang.String permission_type, java.lang.String permission_name, long[] key);

パラメータ

説明

Grantee(権限受領者)

権限を適用するユーザー、スキーマまたはロールの名前。PUBLICに指定すると、その行がすべてのユーザーに適用されます。

Permission_schema(パーミッションのスキーマ)

Permissionクラスのロード先のスキーマ。

Permission_type(パーミッション・タイプ)

パーミッションの付与対象となるPermissionクラス。たとえば、あるファイルへのアクセスを定義する場合、パーミッション・タイプはFilePermissionになります。このパラメータには、java.lang.security.Permissionを拡張するクラスの完全修飾名を指定します。クラスがSYSに入っていない場合は、クラス名に接頭辞schema:を付ける必要があります。たとえば、mySchema:myPackage.MyPermissionは、ユーザー生成のパーミッションの有効な名前です。

Permission_name(パーミッション名)

Permissionクラスによって定義されたtarget属性の意味。適切なPermissionクラスで関連する名前を調べてください。

Row_ number(行番号)

パーミッションを付与または制限すると戻される番号で、enable、disableまたはdeleteの各メソッドに使用します。

注意:
ポリシー表のPolicyTablePermission行の名前には、#で区切られたパーミッション・タイプとパーミッション名の両方が含まれています。たとえば、ファイルを読み取るための管理権限をユーザーに付与する場合は、この行の名前にjava.io.FilePermission#readを含めます。Permissionクラスとパーミッション名は#で区切ります。

例10-3に、PolicyTableの変更方法を示します。

例10-3 PolicyTableパーミッションの付与

この例では、JAVA_ADMINロールが割り当てられているSYSが、Larryに、FilePermissionについてPolicyTableを更新するパーミッションを付与します。このパーミッションが付与されると、Larryは他のユーザーにファイルの読取り、書込みおよび削除のパーミッションを付与できます。

REM Connect as SYS, which is assigned JAVA_ADMIN role, to give Larry permission
REM to modify the PolicyTable
connect SYS as SYSDBA
Enter password: password

REM SYS grants Larry the right to administer permissions for
REM FilePermission
call dbms_java.grant_policy_permission('LARRY', 'SYS', 'java.io.FilePermission', '*');

パーミッションの作成

独自のパーミッション・タイプを作成する手順は、次のとおりです。

1. ユーザーのパーミッションの作成とロード
java.security.Permissionクラスを拡張して、独自のパーミッションを作成します。ユーザーが定義するパーミッションはすべて、Permissionを拡張したものである必要があります。次の例では、MyPermissionを作成します。これは、BasicPermission (Permissionを拡張するパーミッション)を拡張するパーミッションです。

package test.larry;
import java.security.Permission;
import java.security.BasicPermission;

public class MyPermission extends BasicPermission
{

public MyPermission(String name)
{
super(name);
}

public boolean implies(Permission p)
{
boolean result = super.implies(p);
return result;
}
}

2. 指定したユーザーへの管理とアクションのパーミッションの付与
パーミッションを作成すると、作成者がそのパーミッションの所有者になります。所有者には、暗黙的に管理パーミッションが付与されます。つまり、所有者はこのパーミッションの管理者になり、grant_policy_permission()を実行できます。管理パーミッションを付与されたユーザーは、ユーザー定義のパーミッションについてポリシー表を更新できます。

たとえば、LARRYがMyPermissionというパーミッションを作成した場合は、本人のみが自分または他のユーザーのためにgrant_policy_permission()をコールできます。このメソッドは、MyPermissionに対する権限を付与できるユーザーについて、PolicyTableを更新します。次のコードでその方法を示します。

REM Since Larry is the user that owns MyPermission, Larry connects to
REW the database to assign permissions for MyPermission.
connect larry
Enter password: password

REM As the owner of MyPermission, Larry grants himself the right to
REM administer permissions for test.larry.MyPermission within the JVM
REM security PolicyTable. Only the owner of the user-defined permission
REM can grant administrative rights.
call dbms_java.grant_policy_permission ('LARRY', 'LARRY', 'test.larry.MyPermission', '*');

REM commit the changes to PolicyTable
commit;

管理権限を付与された後は、作成したパーミッションに対してアクションのパーミッションを付与できます。たとえば、次のSQL文は、LARRYにMyPermission内のすべてのアクションを実行するパーミッションを付与し、DAVEには「act.」で始まるアクションのみを実行するパーミッションを付与します。

REM Since Larry is the user that creates MyPermission, Larry connects to
REW the database to assign permissions for MyPermission.
connect larry
Enter password: password

REM Once able to modify PolicyTable for MyPermission, Larry grants himself
REM full permission for MyPermission. Notice that the Permission is prefixed
REM with its owner schema.
call dbms_java.grant_permission( 'LARRY', 'LARRY:test.larry.MyPermission', '*', null);

REM Larry grants Dave permission to do any actions that start with 'act.*'.
call dbms_java.grant_permission
('DAVE', 'LARRY:test.larry.MyPermission', 'act.*', null);

REM commit the changes to PolicyTable
commit;

3. パーミッションを使用したセキュリティ・チェックの実装
MyPermissionに対してパーミッションを作成、ロードおよび割り当てた後は、パーミッションをチェックするためにSecurityManagerのコールを実装する必要があります。次の例には、sensitive()、act()、print()およびhello()の4つのメソッドがあります。前述の手順のSQLを使用してパーミッションが付与されているため、この例のクラスでは次のユーザーがメソッドを実行できます。

- LARRYはすべてのメソッドを実行できます。

- DAVEには、act()メソッドのみを実行するパーミッションが付与されています。

- print()メソッドとhello()メソッドはすべてのユーザーが実行できます。print()メソッドはパーミッションをチェックしません。そのため、すべてのユーザーがこれを実行できます。hello()メソッドはAccessController.doPrivileged()を実行します。つまり、このメソッドはLARRYに割り当てられたパーミッションを使用して実行します。これは定義者権限と呼ばれます。

package test.larry;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;

import java.sql.Connection;
import java.sql.SQLException;

/**
* MyActions is a class with a variety of public methods that
* have some security risks associated with them. We will rely
* on the Java security mechanisms to ensure that they are
* performed only by code that is authorized to do so.
*/

public class Larry {

private static String secret = "Larry's secret";
MyPermission sensitivePermission = new MyPermission("sensitive");

/**
* This is a security sensitive operation. That is it can
* compromise our security if it is executed by a "bad guy".
* Only larry has permission to execute sensitive.
*/
public void sensitive()
{
checkPermission(sensitivePermission);
print();
}

/**
* Will display a message from Larry. You must be
* careful about who is allowed to do this
* because messages from Larry may have extra impact.
* Both larry and dave have permission to execute act.
*/
public void act(String message)
{
MyPermission p = new MyPermission("act." + message);
checkPermission(p);
System.out.println("Larry says: " + message);
}

/**
* display secret key
* No permission check is made; anyone can execute print.
*/
private void print()
{
System.out.println(secret);
}

/**
* Display "Hello"
* This method invokes doPrivileged, which makes the method run
* under definer's rights. So, this method runs under Larry's
* rights, so anyone can execute hello. Only Larry can execute hello
*/
public void hello()
{
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() { act("hello"); return null; }
});
}

/**
* If a security manager is installed ask it to check permission
* otherwise use the AccessController directly
*/
void checkPermission(Permission permission)
{
SecurityManager sm = System.getSecurityManager();
sm.checkPermission(permission);
}
}

パーミッションの使用可能または使用禁止

パーミッションを定義する行を作成した場合は、その行が適用されないように使用禁止にできます。ただし、行アクションを再度実行する場合には、その行を使用可能にできます。不要になった行は表から削除できます。行を削除するには、最初にその行を使用禁止にする必要があります。行を使用禁止にしないと、削除できません。

行を使用禁止にするには、次のいずれかのメソッドを使用できます。

- revoke_permission()
このメソッドには、grant()メソッドおよびrestrict()メソッドと同じパラメータを指定します。これは、指定されたパラメータと一致するすべての行をポリシー表全体で検索します。

- disable_permission()
このメソッドは、ポリシー表の1行のみを使用禁止にします。そのためには、パラメータとしてこのメソッドにポリシー表のキーを指定します。このキーは、パーミッションを使用可能にしたり、削除する場合にも必要になります。パーミッションのキー番号を取り出すには、次のいずれかを実行します。

- パーミッションの付与コールまたは制限コールで戻されたキーを保存します。そのパーミッションを使用可能または使用禁止にする必要がないと判断した場合は、パーミッション番号を戻さない付与コールまたは制限コールを使用できます。

- DBA_JAVA_POLICYまたはUSER_JAVA_POLICYを参照して、適切なパーミッションのキー番号を調べます。

DBMS_JAVAを使用してパーミッションを使用禁止にするには、次のように記述します。

procedure revoke_permission (grantee varchar2, permission_type varchar2, permission_name varchar2, permission_action varchar2)

procedure disable_permission (key number)

Javaを使用してパーミッションを使用禁止にするには、次のように記述します。

void oracle.aurora.rdbms.security.PolicyTableManager.revoke (java.lang.String grantee, java.lang.String permission_type,
java.lang.String permission_name, java.lang.String permission_action_type);

void oracle.aurora.rdbms.security.PolicyTableManager.disable (long key);

DBMS_JAVAを使用してパーミッションを使用可能にするには、次のように記述します。

procedure enable_permission (key number)

Javaを使用してパーミッションを使用可能にするには、次のように記述します。

void oracle.aurora.rdbms.security.PolicyTableManager.enable (long key);

DBMS_JAVAを使用してパーミッションを削除するには、次のように記述します。

procedure delete_permission (key number)

Javaを使用してパーミッションを削除するには、次のように記述します。

void oracle.aurora.rdbms.security.PolicyTableManager.delete (long key);

パーミッション・タイプ

パーミッションを付与または制限する場合は、パーミッション・タイプを指定する必要があります。アクセス制御に使用できるパーミッション・タイプは次のとおりです。

- Java 2の許可タイプ

- Oracle固有のパーミッション・タイプ

- java.security.Permissionを拡張するユーザー定義のパーミッション・タイプ

表10-1は、インストールされているパーミッション・タイプの一覧です。

表10-1 事前定義のパーミッション

タイプ

パーミッション

Java 2

- java.util.PropertyPermission

- java.io.SerializablePermission

- java.io.FilePermission

- java.net.NetPermission

- java.net.SocketPermission

- java.lang.RuntimePermission

- java.lang.reflect.ReflectPermission

- java.security.SecurityPermission

Oracle固有

- oracle.aurora.rdbms.security.PolicyTablePermission

- oracle.aurora.security.JServerPermission

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

Oracle固有のパーミッションについて説明します。

- oracle.aurora.rdbms.security.PolicyTablePermission
このパーミッションは、ポリシー表を更新できるユーザーを制御します。特定のパーミッション・タイプについてポリシー表を更新する権限を付与されたユーザーは、一部のリソースへのアクセスを制御できます。

Oracle JVMを初期化した後、JAVA_ADMINロールのみがPolicyTablePermissionを使用してポリシー表の管理権限を付与できます。この権限を付与されると、そのユーザーは、自分の付与パーミッションおよび制限パーミッションを使用してポリシー表を更新できます。

ポリシー表の更新権限を付与する場合は、DBMS_JAVAパッケージのgrant_policy_permission()メソッドを使用できます。表を更新したら、DBA_JAVA_POLICYまたはUSER_JAVA_POLICYビューのいずれかを表示して、パーミッションを付与したユーザーを参照できます。

- oracle.aurora.security.JServerPermission
このパーミッションを使用して、Oracle JVMリソースへのアクセス権を付与および制限します。JServerPermissionは、BasicPermissionを拡張するパーミッションです。次の表は、JServerPermissionによってアクセス権を付与するパーミッション名を示します。

表10-2 JServerPermissionの説明

Grantee(権限受領者)

パーミッション・タイプ

パーミッション名

パーミッションの付与または制限

アクション

JAVADEBUGPRIV

SYS:oracle.aurora.security.JServerPermission

Debug

付与

NULL

SYS

SYS:oracle.aurora.security.JServerPermission

*

付与

NULL

SYS

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.java.*

付与

NULL

SYS

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.oracle.aurora.*

付与

NULL

SYS

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.oracle.jdbc.*

付与

NULL

PUBLIC

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.*

付与

NULL

PUBLIC

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.java.*

制限

NULL

PUBLIC

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.oracle.aurora.*

制限

NULL

PUBLIC

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.oracle.jdbc.*

制限

NULL

JAVA_DEPLOY

SYS:oracle.aurora.security.JServerPermission

LoadClassInPackage.oracle.aurora.deploy.*

付与

NULL

JAVA_DEPLOY

SYS:oracle.aurora.security.JServerPermission

Deploy

付与

NULL

初期のパーミッションの付与

Oracle JVMを最初に初期化すると、特定のパーミッションを付与された複数のロールが移入されます。次の表は、それらのロールとその初期のパーミッションを示します。

- 表10-3 SYSの初期のパーミッション

- 表10-4 PUBLICのデフォルトのパーミッション

- 表10-5 JAVAUSERPRIVのパーミッション

- 表10-6 JAVASYSPRIVのパーミッション

- 表10-7 JAVADEBUGPRIVのパーミッション

JAVA_ADMINロールには、すべてのパーミッションについてポリシー表を変更するためのアクセス権が付与されます。SYSを含むすべてのDBAにはJAVA_ADMINが付与されます。表10-1にリストされているパーミッションについては、ポリシー表を更新する完全な管理権限が付与されます。SYSには、JAVA_ADMINのパーミッションの他に、JDKの標準的な機能およびOracle JVMの詳細をサポートするために必要な追加のパーミッションも付与されます。

表10-3は、SYSに付与される追加のパーミッションの一部です。

表10-3 SYSの初期のパーミッション

パーミッション・タイプ

パーミッション名

アクション

oracle.aurora.rdbms.security. PolicyTablePermission

oracle.aurora.rdbms.security.PolicyTablePermission#*

NULL

oracle.aurora.security.JServerPermission

*

NULL

java.net.NetPermission

*

NULL

java.security.SecurityPermission

*

NULL

java.util.PropertyPermission

*

書込み

java.lang.reflect.ReflectPermission

*

NULL

java.lang.RuntimePermission

*

NULL

loadLibrary.xaNative

NULL

loadLibrary.corejava

NULL

loadLibrary.corejava_d

NULL

表10-4は、最初にすべてのユーザーに付与または制限されるパーミッションの一覧です。

表10-4 PUBLICのデフォルトのパーミッション

パーミッション・タイプ

パーミッション名

パーミッションの付与または制限

アクション

oracle.aurora.rdbms.security. PolicyTablePermission

java.lang.RuntimePermission#loadLibrary.*

制限

NULL

java.util.PropertyPermission

*

付与

読取り

user.language

付与

書込み

oracle.net.tns_admin

付与

書込み

java.lang.RuntimePermission

_

付与

NULL

exitVM

付与

NULL

createSecurityManager

付与

NULL

modifyThread

付与

NULL

modifyThreadGroup

付与

NULL

getenv.ORACLE_HOME

付与

NULL

getenv.TNS_ADMIN

付与

NULL

preferences

付与

NULL

loadLibrary.*

制限

NULL

oracle.aurora.security. JServerPermission

LoadClassInPackage.* (LoadClassInPackage.java.*、LoadClassInPackage.oracle.aurora.*およびLoadClassInPackage.oracle.jdbc.*を除く)

付与

NULL

表10-5は、最初にJAVAUSERPRIVロールに付与されるパーミッションの一覧です。

表10-5 JAVAUSERPRIVのパーミッション

パーミッション・タイプ

パーミッション名

アクション

java.net.SocketPermission

*

接続、解決

java.io.FilePermission

<<ALL FILES>>

読取り

java.lang.RuntimePermission

stopThread、getProtectionDomain、accessClassInPackage.*およびdefineClassInPackage.*

NULL

表10-6は、最初にJAVASYSPRIVロールに付与されるパーミッションの一覧です。

表10-6 JAVASYSPRIVのパーミッション

パーミッション・タイプ

パーミッション名

アクション

java.io.SerializablePermission

*

適用できるアクションなし

java.io.FilePermission

<<ALL FILES>>

読取り、書込み、実行、削除

java.net.SocketPermission

*

アクセプト、接続、リスニング、解決

java.sql.SQLPermission

setLog

NULL

java.lang.RuntimePermission

createClassLoader

NULL

getClassLoader

NULL

setContextClassLoader

NULL

setFactory

NULL

setIO

NULL

setFileDescriptor

NULL

readFileDescriptor

NULL

writeFileDescriptor

NULL

表10-7は、最初にJAVADEBUGPRIVロールに付与されるパーミッションの一覧です。

表10-7 JAVADEBUGPRIVのパーミッション

パーミッション・タイプ

パーミッション名

アクション

oracle.aurora.security.JServerPermission

Debug

NULL

ロールに割り当てられる一般的なパーミッション定義

Oracle8i Databaseリリース8.1.5では、JAVASYSPRIV、JAVAUSERPRIVまたはJAVADEBUGPRIVロールをスキーマに付与することによって、Oracle JVMセキュリティが制御されていました。Oracle Database 12cリリース1 (12.1)では、これらのロールは許可グループとして存在しています。ユーザー独自のパーミッションの組合せを設定および定義できます。パーミッションを定義した後は、任意のユーザーまたはロールに任意のパーミッションの組合せを付与できます。付与されたユーザーには、そのロールに設定されている内容と同じパーミッションが付与されます。さらに、追加のパーミッションが必要な場合は、指定したユーザーまたはロールのいずれかに個別にパーミッションを追加できます。ポリシー表に定義されたパーミッションには累積の効果があります。

注意:
PropertyPermissionの書込みアクションを使用して付与したプロパティへの書込み権限は、現行バージョンでは全ユーザーに付与されません。かわりに、JAVA_ADMINからこのパーミッションを付与するか、またはJAVASYSPRIVロールを付与することによって、このパーミッションを取得する必要があります。

次の例では、LarryとDaveに次のパーミッションが付与されます。

- LarryにはJAVASYSPRIVパーミッションが付与されます。

- Daveには、JAVADEBUGPRIVパーミッション、およびシステム上の全ファイルへの読取りと書込みのパーミッションが付与されます。

REM Granting Larry the same permissions as those existing within JAVASYSPRIV
grant javasyspriv to larry;

REM Granting Dave the ability to debug
grant javadebugpriv to dave;

commit;

REM I also want Dave to be able to read and write all files on the system
call dbms_java.grant_permission('DAVE', 'SYS:java.io.FilePermission',
'<<ALL FILES>>', 'read,write', null);

関連項目:
「各パーミッションのファイングレイン定義」。

デバッグのパーミッション

デバッグ・ロールJAVADEBUGPRIVは、デバッガを実行するパーミッションを付与するために作成されました。このロールに割り当てられるパーミッションの一覧は、表10-7を参照してください。デバッグ・エージェントをコールするパーミッションを取得するには、次のように、コール元にJAVADEBUGPRIVまたはデバッグJServerPermissionが付与されている必要があります。

REM Granting Dave the ability to debug
grant javadebugpriv to dave;

REM Larry grants himself permission to start the debug agent.
call dbms_java.grant_permission(
'LARRY', 'oracle.aurora.security.JServerPermission', 'Debug', null);

デバッガはサーバー上のコードとデータの両方に広範囲にアクセスできますが、デバッガの使用は開発環境に限定する必要があります。

クラスをロードするためのパーミッション

クラスをロードするには、次のパーミッションが必要です。

JServerPermission("LoadClassInPackage." + class_name)

class_nameには、ロードするクラスの完全修飾名を指定します。

このパーミッションには、システム・パッケージへのロードやシステム・クラスの置換は含まれません。システム・クラスをロードするパーミッションが付与されている場合でも、Oracle Databaseではロードを実行できません。システム・クラスとは、Oracle DatabaseでCREATE JAVA SYSTEM文を使用してインストールされるクラスです。システム・クラスを置換しようとすると、次のエラーがスローされます。

ORA-01031 "Insufficient privileges"

次に、データベースのインストール後、各ユーザーが実行できる処理について説明します。

- SYSはシステム・クラス以外の全クラスをロードできます。

- すべてのユーザーは、java.*、oracle.aurora.*およびoracle.jdbc.*以外のパターンで始まるクラスを自分のスキーマにロードできます。このようなクラスを別のスキーマにロードする場合は、JServerPermission(LoadClassInPackage.class)のパーミッションを付与する必要があります。
次の例は、oracle.aurora.tools.*パッケージにクラスをロードする許可をHRに付与する方法を示します。

dbms_java.grant_permission('HR','SYS:oracle.aurora.security.JServerPermission','LoadClassInPackage.oracle.aurora.tools.*',null);

デフォルトのjava.securityリソースのカスタマイズ

セキュリティ・プロバイダを追加する場合や、デフォルトのjava.securityリソースにリストされているセキュリティ・プロバイダの順序を変更する場合は、代替リソースを作成してデータベースに追加できます。この変更は、リソースのロード後に開始されるすべての新しいOracle JVMセッションに影響を与えます。次の手順を実行して、デフォルトのjava.securityリソースを構成します。

1. 次のファイルを作成します。

$ORACLE_HOME/javavm/lib/security/java.security.alt

2. 次のコマンドを使用して、ファイル$ORACLE_HOME/javavm/lib/security/java.securityの内容を、手順1で作成したファイルにコピーします。

cp $ORACLE_HOME/javavm/lib/security/java.security $ORACLE_HOME/javavm/lib/security/java.security.alt

3. $ORACLE_HOME/javavm/lib/security/java.security.altファイルを編集し、必要な変更を行います。

注意:
サービス・プロバイダまたは定義済デバイスの順序を指定する際に誤りがあると、いくつかの機能が使用できなくなる可能性があります。

4. 次のコマンドを使用して、java.security.altファイルをロードします。

注意:
lib/security/java.security.altファイルをロードするには、SYSとしてログインできる必要があります。

cd $ORACLE_HOME/javavm
loadjava -u sys/<sys_pwd> -v -g public lib/security/java.security.alt

このセキュリティ設定は、データベースから開始される以降のOracle JVMセッションすべてに影響を与えます。ただし、セキュリティ設定の変更はロード・セッションには有効になりません。

注意:
セキュリティ・パラメータを構成するには、それに関する事前の知識が必要です。間違った設定を行うと、正常に操作できなくなることがあります。

関連項目:
このセキュリティ設定の詳細は、http://docs.oracle.com/javase/7/docs/technotes/guides/security/index.htmlを参照してください。

Create or Replace Java System

Create or Replace Java Systemをjava.security.altで実行して、異なるセットのセキュリティ・パラメータをOJVMに付与します。これを実行する前に、次のようにしてすべてのシステム・セッションを再起動します。

sqlplus / as sysdba
shutdown

sqlplus / as sysdba
startup

次のようにして、Create Java Systemを実行します。

sqlplus / as sysdba
create or replace java system

Linux.X64データベースでは、Create Java Systemは使用できません。この場合は、次のコマンドを使用します。

sqlplus / as sysdba
call rehotload();

セキュリティ設定のリストア

元のセキュリティ設定は、次のいずれかの方法でリストアできます。

- 次のコマンドを使用します。

cd $ORACLE_HOME/javavm
dropjava -u sys/<sys_pwd> -v lib/security/java.security.alt

- 次のコマンドを使用します。

sqlplus sys/<sys_pwd> as sysdba
SQL> drop java resource "lib/security/java.security.alt";

データベース認証のメカニズム

次のデータベース認証のメカニズムが使用可能です。

- パスワード認証

- 厳密認証

- プロキシ認証

- シングル・サインオン

Oracle DatabaseでのRuntime.exec機能のセキュアな使用

注意:
この項はDBAおよびセキュリティ管理者を対象としており、Oracle Databaseで実行されているJavaアプリケーションでJava SE機能のRuntime.execをセキュアに使用するためのガイドラインを示します。

java.lang.Runtime.execメソッドはJava SEライブラリにあり、リリース9以降のJava仮想マシン(Java VM)でサポートされており、新しいオペレーティング・システム(OS)プロセスにまたがって、指定されたコマンドおよび引数を新しいプロセスで実行します。SecurityManagerが存在する場合(Java VMがデータベースで実行されている場合は常に存在します)、新しいOSプロセスが開始される前に、関連するパス名に対するファイル実行許可のセキュリティ・チェックが実行されます。DBAまたはセキュリティ管理者は、適切なファイル読取り許可、書込み許可および実行許可を、サーバー側のOSコマンドの実行を認可されているデータベース・ユーザーに選択的に付与する役割を持ちます。さらに、次の各項で説明するように、dbms_java.set_runtime_exec_credentialsプロシージャを使用して、生成されたコマンドのOSユーザー・アイデンティティを制御することを強くお薦めします。

設計上、Runtime.execおよびjava.lang.ProcessBuilderクラスとjava.lang.Processクラスの関連機能は、新しく作成されたプロセスと関連付けられたユーザーのアイデンティティを制御しません。Java VMのデフォルト動作を含むほとんどのJava実装では、分岐プロセスは親プロセスのアイデンティティ(Oracle DatabaseのOracle OSユーザー)を使用して実行されます。セキュリティ上の理由で、Runtime.exec機能により分岐されたプロセスは、弱い権限を付与されたOSアイデンティティを使用して実行することをお薦めします。dbms_java.set_runtime_exec_credentialsプロシージャは、指定されたデータベース・ユーザー/スキーマを特定のOSアカウントにバインドするメカニズムを提供します。DBAは、できるかぎり小さい権限を持つOSアカウントにRuntime.execコールを発行して、データベース・ユーザーをバインドする必要があります。次のコールは、データベース・ユーザー/スキーマDBUSERをOSのosuserアカウントに関連付けます。

dbms_java.set_runtime_exec_credentials('DBUSER', 'osuser', 'ospass');

この結果、DBUSERにより発行されたRuntime.execコマンドを実行するために生成されるOSプロセスは、osuserのアイデンティティを使用して実行されます。set_runtime_exec_credentialsプロシージャを使用するには、SYSユーザーである必要があります。

関連項目:
「set_runtime_exec_credentials」

11 JNDIに対するOracle JVMのネイティブ・サポート

この章では、Java Naming and Directory Interface (JNDI)に対するOracle JVMのサポートについて説明します。この章の内容は、次のとおりです。

- JNDIに対するOracle JVMのサポートの概要

- JNDIに対するOracle JVMのサポートの要件

- OJDSのコマンドライン・ツール

- OJDSのAPIおよびクラス

JNDIに対するOracle JVMのサポートの概要

JNDIに対するOracle JVMのネイティブ・サポートによって、特定のデータベース接続情報を含むOracleデータ・ソース・オブジェクトをディレクトリ構造内の名前によってバインドできます。この名前を使用して、アプリケーションで接続を確立するための特定の接続情報を取得できます。また、アプリケーションを変更せずに、特定の名前が解決される関連オブジェクトのみを変更することにより、データベース接続プロパティおよび実際のソース・データベースを変更することもできます。さらに、この機能は、オブジェクトおよびオブジェクト参照を格納するための汎用的なディレクトリ・サービスも提供します。

oracle.aurora.jndi.ojdsというOracle Java Directory Service (OJDS)パッケージは、JNDIのサポートを実装するためのAPIを提供します。oracle.aurora.jndi.ojdsパッケージに存在するAPIの詳細は、「OJDSのAPIおよびクラス」を参照してください。

JNDIに対するOracle JVMのサポートの要件

この項では、Oracle JVMでJNDIをサポートするための実装要件について説明します。この項の内容は次のとおりです。

- ネームスペース

- Oracle Java Directory ServiceのJNDIネームスペース・プロバイダ

- ネームスペース・ブラウザ

ネームスペース

ネームスペースの表記は、一般的なUNIXファイル・システム構造の場合と同様です。ルート・ディレクトリおよびディレクトリ・セパレータは、スラッシュ記号(/)で表記されます。ルート・ディレクトリはSYSが所有し、SYSのみがその下に新規のサブディレクトリを作成できます。

OJDSのインストール・プロセス中に、次の2つのディレクトリ(DirContexts)が作成されます。

- /publicディレクトリ
/publicディレクトリはテスト用のパブリック領域であり、すべてのユーザーがこのディレクトリ内のオブジェクトをバインド、削除または参照できます。

- /etcディレクトリ
/etcディレクトリは、クライアントが必要とするすべての本番タイプ・オブジェクトのデプロイメント用の領域であり、更新または削除されないように保護されます。/etcディレクトリへの書込みはSYSユーザーのみが実行できますが、読取りはすべてのユーザーが実行できます。

オブジェクト許可

ディレクトリ構造に格納されたオブジェクトには、許可を割り当てることができます。これらの許可は、次の許可を組み合せたものです。

- 読取り

- 書込み

- 実行

次の表で、ディレクトリ構造に格納されたオブジェクトに割り当てることができる許可について説明します。

アクション

親コンテキストの許可

子(obj/ctx)の許可

bind

書込み

NA

unbind

書込み

書込み

createSubcontext

書込み

NA

getAttributes

読取り

読取り

rebind

書込み

書込み

destroySub context

書込み

書込み

list

読取り

読取り

listBindings

読取り

読取り

lookup

読取り

読取り

lookupLink

読取り

読取り

rename (target)

書込み

書込み(存在する場合)

rename (source)

読取り

読取り

注意:
操作を正常に実行するには、すべての親コンテキストに実行許可があることが必要です。

永続記憶域表、索引および順序

OJVMSYSが所有するデータベース表には、各オブジェクトの次の詳細が格納されます。

- ネームスペース・メタデータ

- バウンド名

- 属性

- パーミッション

- 格納されたオブジェクト表現

初期のコンテキストおよび許可

次の表に、インストール時にデフォルトで作成されるコンテキストを示します。

名前

所有者

読取り

書込み

実行

/

SYS

PUBLIC

SYS

PUBLIC

/public

SYS

PUBLIC

PUBLIC

PUBLIC

/etc

SYS

PUBLIC

SYS

PUBLIC

オブジェクトおよびコンテキストのデフォルト許可

コンテキストが作成された場合や、オブジェクトがOJDSにバインドされた場合、コンテキストを作成するユーザーまたはスキーマに読取り許可と実行許可が付与されます。

Oracle Java Directory ServiceのJNDIネームスペース・プロバイダ

この項では、Oracle Java Directory Serviceの次の概念について説明します。

- ディレクトリ・コンテキスト

- StateFactory

- ObjectFactory

- OJDS URLのサポート

- クライアント・クラスパス

ディレクトリ・コンテキスト

Oracle Java Directory Service (OJDS)は、javax.naming.directory.DirContextコンテキストで指定されているとおりにインタフェースを実装する必要があります。javax.naming.directory.DirContextコンテキスト、oracle.aurora.jndi.ojds.OjdsServerContextコンテキストおよびoracle.aurora.jndi.ojds.OjdsClientContextコンテキストは、オブジェクトに関連付けられている属性を調査および更新するメソッドを提供し、サーバー側とクライアント側のそれぞれの実行でのディレクトリ検索を可能にします。

次の表で、コンテキストを作成または使用する際に使用可能なJNDIプロパティについて説明します。

パッケージ名

説明

java.naming.factory.initial

アプリケーションの初期コンテキストの作成に使用するクラスを指定します。oracle.aurora.jndi.ojdsパッケージは、InitialDirContextを作成するためにこのプロパティで使用するoracle.aurora.jndi.ojds.OjdsInitialContextFactoryを定義します。

java.naming.security.principal

データベース接続を作成するためのユーザーIDを指定します。このプロパティには値を指定する必要があります。

java.naming.security.credentials

データベース接続を作成するためのパスワードを指定します。このプロパティには値を指定する必要があります。

java.naming.provider.url

データベース接続を作成するための接続URLを指定します。このプロパティはオプションです。

java.naming.factory.url.pkgs

特定のJNDI実装に対するURLハンドラの、コロンで区切られたリストです。oracle.aurora.jndi.ojds.OjdsURLContextFactoryクラスは、OJDS URLに基づいてコンテキストを戻します。

StateFactory

StateFactoryは、Javaオブジェクトを実装側のJNDIプロバイダに格納できるオブジェクトに変換します。OJDSによってすべてのオブジェクトが変換され、シリアライズ・オブジェクトにバインドされます。OJDSは、この変換に関するjava.io.Serializableインタフェースの仕様およびJava Object Serialization Specificationに準拠しています。シリアライズされたオブジェクトは、OJDS永続ストアに格納されます。OJDSでは、外部のStateFactoryはサポートされていません。

ObjectFactory

ObjectFactoryは、実装側のJNDIプロバイダに格納されているオブジェクトを取得して、Javaオブジェクトに変換します。OJDSでは、外部のObjectFactoryはサポートされていません。シリアライズ・オブジェクトが、OJDS永続ストアから取得されたバイナリ形式に基づいて作成されます。オブジェクトがデシリアライズされると、OJDSによってそのオブジェクトは次のいずれかの方法で処理されます。

- オブジェクトがContextの場合、connectionフィールドとenvフィールドが設定され、DirContextが戻されます。

- オブジェクトがjavax.naming.Referenceの場合、DirectoryManager.getObjectInstanceメソッドを使用してオブジェクトを作成できます。

- オブジェクトがContextでもjavax.naming.Referenceでもない場合、オブジェクトはそのままユーザーに戻されます。

オブジェクトを指定する取得済バイトは、java.io.Serializableインタフェース標準に準拠している必要があります。オブジェクトを実装するクラスがクライアントで変更されると、オブジェクトのデシリアライズに失敗することがあります。このため、オブジェクト・バイトと、オブジェクト・バイトをデシリアライズするクラスまたはオブジェクト・ストリームとの互換性を保つように注意する必要があります。

OJDS URLのサポート

OJDSでは、次の形式で指定するURLがサポートされています。

ojds://jdbc_connection_url/path…/object

前述の構文の各要素は次のとおりです。

- jdbc_connection_urlは、サポートされているJDBC接続URLの1つです。URLには、ディレクトリに接続するためのjdbc_connection_urlを指定する必要があります。

注意:
OJDSプロバイダでは、JDKベースの外部クライアントに対してThinとOCIの両方のURLがサポートされています。たとえば、ThinドライバとOCIドライバにはそれぞれ次のURLを使用できます。

thin:localhost:5521:mysid
oci:22.133.242:5521:mysid

ただし、サーバーでのOJDS URLは、Thin接続タイプにのみサポートされています。URL接続を完了するには、Context.SECURITY_PRINCIPALおよびContext.SECURITY_CREDENTIALSの値を設定する必要があります。

- pathは、UNIXタイプのファイル・システムと同様の、スラッシュ脚注1で区切られたリストです。これは、ディレクトリ・ツリー内のノードを表しています。

- objectは、コンテキスト内の実際の終端オブジェクト名です。このオブジェクトを省略した場合、パスはスラッシュ(/)で終了します。このような場合は、このパスをルートとして表すDirContextが戻されます。

例

次のコード・スニペットは、ユーザーHRとして、接続されたOCIドライバを使用してディレクトリ/one/two内のMyObj型のオブジェクトmyobjを参照する方法を示しています。

import javax.naming.*;
.
.
.
Hashtable env = new Hashtable();
env.put(”java.naming.security.principal”,”HR”);
@ env.put(”java.naming.security.credentials”,”<password>”);
MyObj obj = (MyObj)(new InitialDirContext(env)).lookup(ojds://oci:host1:5521:mysid/one/two/myobj”);

クライアント・クラスパス

JDKクライアントがOJDSを使用するためには、$ORACLE_HOME/jdbc/lib/ojdbc6.jarおよび$ORACLE_HOME/javavm/lib/aurora.zip jarファイルをクラスパスに追加する必要があります。

ネームスペース・ブラウザ

ネームスペース・ブラウザを使用すると、OJDSに格納されたオブジェクトの許可およびプロパティを参照できます。既存のojvmjavaユーティリティが拡張され、次の表で説明する操作がサポートされています。

関連項目:
ojvmjavaユーティリティの詳細は、「ojvmjavaツール」を参照してください。

コマンド名

説明

ls

UNIXのlsコマンドと同様に、コンテキストの内容を一覧表示します。

rm

コンテキストまたはオブジェクトを削除します。

mkdir

OJDSでコンテキストを作成します。

chown

特定のコンテキストやオブジェクトなどの所有者を変更します。

chmod

オブジェクトまたはコンテキストに対する権限を変更します。

cd

作業コンテキストを変更します。

pwd

現行作業コンテキストを一覧表示します。

ln

UNIXのシンボリック・リンクと同様に、別の名前を使用して同じオブジェクトを参照します。

mv

コンテキスト(またはオブジェクト)の古い名前を変更するか、新しい名前に再バインドします。

bind

オブジェクト参照またはネーミング・コンテキストをJNDIネームスペースにバインドします。

bindds

データ・ソース・オブジェクトを特定のコンテキストにバインドします。

bindurl

URLオブジェクトを特定のコンテキストにバインドします。

OJDSのコマンドライン・ツール

拡張されたojvmjavaコマンドを使用すると、OJDSを操作および参照できます。この項では、次のコマンドについて説明します。

- lsコマンド

- cdコマンド

- pwdコマンド

- chownコマンド

- mkdirコマンド

- rmコマンド

- lnコマンド

- mvコマンド

- chmodコマンド

- bindコマンド

- binddsコマンド

- bindurlコマンド

lsコマンド

lsコマンドは、コンテキストの内容を表示します。

構文

ls [options] [context1] [context2] [obj|context]...

オプション

次の表で、lsコマンドのオプションについて説明します。

オプション

説明

Context obj

一覧表示するコンテキストまたはオブジェクトの名前を指定します。

-l

名前、作成時刻、所有者、権限などを含む長い形式でコンテンツを表示します。オブジェクトのクラスを表示します。

dir

UNIXのls –dコマンドと同様に、コンテキストのみを表示します。

ldir

–lコマンドのように長い形式でコンテンツを表示しますが、UNIXの–ldと同様にバインドされたオブジェクトを無視します。

R

子コンテキスト全体を再帰的に一覧表示します。

例

次のコマンドは、ルート・コンテキストの内容を短い形式で表示します。

$ ls /

etc/      public/

次のコマンドは、ルート・コンテキストの内容を長い形式で表示します。

$ ls -l
Read      Write    Exec        Owner    Date       Time      Type       Name
PUBLIC    SYS      PUBLIC      SYS      Dec 14     14:59     Context    etc
PUBLIC    PUBLIC   PUBLIC      SYS      Dec 14     14:59     Context    public

cdコマンド

cdコマンドは、作業コンテキストを変更します。このコマンドは、UNIXのcdコマンドと同様に、ディレクトリを変更します。

例

次のコマンドは、コンテキストをルート・コンテキストに変更します。

$ cd /

pwdコマンド

pwdコマンドは、現行作業コンテキストを一覧表示します。

例

現行コンテキストが/test/alphaの場合、pwdコマンドの出力は次のようになります。

$ pwd

/test/alpha/

chownコマンド

chownコマンドは、コンテキストまたはオブジェクトの所有権を変更します。

注意:
コンテキストまたはオブジェクトの所有権を変更できるのは、SYSユーザーのみです。

構文

chown [options] {user | role} <object name>

オプション

次の表で、chownコマンドのオプションについて説明します。

オプション

説明

User role

所有者になるユーザーまたはロールの名前を指定します。

<object name>

変更するコンテキストまたはオブジェクトの名前を指定します。

-R

次のものの所有権を再帰的に変更します。

- コンテキスト

- コンテキスト内のすべてのサブコンテキスト

- コンテキストおよびサブコンテキストに含まれるすべてのオブジェクト

例

次のコマンドは、HRを/alpha/beta/gammaコマンドの所有者にします。

$ chown HR /alpha/beta/gamma

mkdirコマンド

mkdirコマンドは、指定した名前でコンテキストを作成します。

注意:
新規のコンテキストを作成するには、ターゲット・コンテキストに対する書込み許可を持っている必要があります。

オプション

次の表で、mkdirコマンドのオプションについて説明します。

オプション

説明

<name>

作成するコンテキストの名前を指定します。

-path | -p

中間コンテキストが存在しない場合は作成します。

例

次のコマンドは、/testコンテキストがすでに存在する場合に、/test/alphaというコンテキストを作成します。

mkdir /test/alpha

次のコマンドは、/test/alpha/betaコンテキストが存在しない場合に、/test/alpha/beta/gammaというコンテキストを作成します。

$ mkdir -path /test/alpha/beta/gamma

rmコマンド

rmコマンドは、UNIXシェル・コマンドのrmと同様です。このコマンドは、オブジェクトまたはコンテキストを、その内容も含めて削除します。

注意:
オブジェクトを削除するには、そのオブジェクトを含むコンテキストに対する書込み権限が必要です。

オプション

次の表で、rmコマンドのオプションについて説明します。

オプション

説明

<Object>

削除するコンテキストまたはオブジェクトの名前を指定します。

-recurse | -r

コンテキストを仮定し、コンテキストとその内容を再帰的に削除します。

例

次のコマンドは、オブジェクト/test/bankを削除します。

rm /test/bank

次のコマンドは、コンテキスト/test/release3とその内容を削除します。

rm -r /test/release3

lnコマンド

lnコマンドは、UNIXのlnコマンドと同様です。リンクとは、コンテキストまたはオブジェクトのシノニムのことです。コンテキストまたはオブジェクトを移動すると、コンテキストまたはオブジェクトへの参照が無効になることがあります。lnコマンドは、古い名前でリンクを作成し、古い名前と新しい名前の両方でオブジェクトにアクセスできるようにします。

構文

ln [-symbolic | -s] <object> <link>

オプション

次の表で、lnコマンドのオプションについて説明します。

オプション

説明

-s

<link>への<object>のソフト・リンクを作成します。

<object>

コンテキストまたはオブジェクトの名前を指定します。

<link>

コンテキストまたはオブジェクトをリンクする先のシノニムの名前を指定します。

例

次のコマンドは、オブジェクト名がnewに変更された後も、oldオブジェクトへのアクセスを保持します。

$ mv old new
$ ln new old

mvコマンド

mvコマンドは、コンテキストまたはオブジェクトの名前を新しい名前に変更(または古い名前を再バインド)します。

構文

mv <old> <new>

例

次のコマンドは、コンテキスト/test/fooの名前を/test/barに変更します。

$ mv /test/foo /test/bar

chmodコマンド

chmodコマンドは、UNIXシェル・コマンドのchmodと同様です。このコマンドは、コンテキストまたはオブジェクトに対するユーザーまたはロールの権限を変更します。

注意:
オブジェクトに対する権限を変更できるのは、SYSユーザーまたはオブジェクト所有者のみです。

関連項目:
オブジェクト許可の詳細は、「オブジェクト許可」を参照してください。

構文

chmod [options] {+|-} {r|w|x} {<user> | <role>, ...} <objectname>

オプション

次の表で、chmodコマンドのオプションについて説明します。

オプション

説明

+/-rwx

読取り、書込みまたは実行の権限を追加(+)または削除(-)します。

<user> | <role>

追加または削除する権限を所有するユーザーまたはロール

<objectname>

権限を変更するコンテキストまたはオブジェクト

-R

権限を再帰的に変更します。

例

次の例では、/alpha/beta/gammaコンテキストの権限をHRおよびNANCYに変更します。

$ chmod +x HR,NANCY /alpha/beta/gamma

注意:
複数のスキーマはカンマでのみ区切ります。

次の例では、/alpha/beta/gammaコンテキストでのHRの書込み権限を削除します。

$ chmod -w HR /alpha/beta/gamma

bindコマンド

bindコマンドは、オブジェクト参照またはコンテキストをJNDIネームスペースにバインドします。

構文

bind <objectname> [options] [-context] [-rebind] {-class | -c <classname>} [-factory | -f <factory>] [-location | -l <URL>][-string <type_name>

<string_value> [-string <type_name> <string_value> ...]] [-binary <type_name> <string_value> [-binary <type_name> <string_value> ...]]

オプション

次の表で、bindコマンドのオプションについて説明します。

オプション

説明

<objectname>

バインド先のオブジェクトの名前

-context

バインドするオブジェクトは、ContextまたはInitialContextです。

-rebind

JNDI名がすでに存在する場合、そのバインド先のオブジェクトをこのオブジェクトで置換します。

-class <classname>

バインドされるオブジェクトのクラス名を指定します。

-factory <factory>

オブジェクトを作成するためのファクトリ・クラス名を指定します。JNDIでは、オブジェクトを作成する際にこれが使用されます。

-location <URL>

デフォルトの場所を使用しない場合、ファクトリの場所を指定します。これにはJNDI URLが使用されます。

-string <type_name> <string_value>

オブジェクトの文字列参照属性をタイプ名および値で指定します。

-binary <type_name> <string_value>

オブジェクトのバイナリ参照属性をタイプおよびバイナリ値で指定します。指定された16進文字列値は、バイナリに変換されます。

例

次のコマンドは、オブジェクト参照をネームスペースにバインドします。文字列およびバイナリ属性が参照に提供されます。

bind /tmp/myprinter  -class gen.Inkjet  -factory gen.InkjetFactory  -string PRINTERNAME co2  -binary DPI  0X12C

binddsコマンド

このコマンドは、DataSourceオブジェクトをJNDIネームスペースにバインドします。このコマンドは、指定されたオプションに応じて、汎用データ・ソース、XAデータ・ソースまたはプールされたデータ・ソースをバインドします。

注意:
Oracle JVMでは、kprbドライバおよびThinドライバのみがサポートされています。

構文

bindds <object_name> [options] [-help | -h] [-describe | -d] [-version | -v] [-dstype <datasource>]

[-host <hostname> -port <portnum> -sid <SID> -driver <driver_type>] [-url <db_url>]

[-g | -grant {<user> | <role>} [,{<user> | <role>}]...] [-recursiveGrant | -rg {<user> |<role>}

[,{<user> | <role>}]...] [-rebind] [-user | -u <user>]

オプション

次の表で、binddsコマンドのオプションについて説明します。

オプション

説明

<objectname>

オブジェクトをバインドする名前を指定します。

-help

ヘルプ・メッセージを指定します。

-describe

ツール操作を要約します。

-version

バージョン番号を指定します。

-dstype <type>

次のいずれかのタイプから、データ・ソース・タイプを指定します。

- なし(OracleDataDourceの場合)

- xa (OracleXADatasourceの場合)

- pool (OracleConnectionPoolDataSourceの場合)

-host <hostname> -port <portnum> -sid <SID> -driver <drv_type>

データベースの場所、およびデータベースに接続するためのドライバ・タイプを指定します。あるいは、-urlオプション内でこの情報をURL形式で指定することもできます。-sidオプションのデフォルト値は、ORCLです。-driverオプションの値は、thin、ociまたはkprbです。

-url <db_url>

このJDBC URLは、データベースの場所を指定します。

-grant <user|role>, <user|role>…

読取り権限および実行権限を<user>名と<role>名のシーケンスに付与します。再バインドする際には、読取り権限または実行権限を持つ既存のユーザーまたはロールを<user>名および<role>名で置き換えます。

-recursiveGrant <user|role>, <user|role>….

指定されたオブジェクトおよびオブジェクトが存在するすべてのコンテキストに、読取り許可および実行許可を再帰的に付与します。コンテキストの許可レベルがSYSの場合、そのコンテキストに対する付与は無視されます。

-rebind

DataSourceオブジェクトがすでに存在する場合、このオプションを指定して、既存のデータ・ソースをこの新しいオブジェクトで上書きする必要があります。そうしない場合、このオプションでバインドは実行されません。

-user <user>

データベースに接続するためのユーザー名を指定します。ユーザー名をDataSourceオブジェクト内に格納します。データベース接続の作成時にJNDIコンテキスト内でユーザー名を指定しない場合は、このユーザー名が使用されます。

例

次の例では、ds1データ・ソースがネームスペースにバインドされます。

bindds /test/ds1 -host localhost -port 1522 -sid orcl -driver thin
bindds /test/ds1 -url jdbc:oracle:thin:@localhost:1522:orcl

この例では、汎用データ・ソース(OracleDataSource)に対してJDBC Thinドライバを使用します。

bindurlコマンド

bindurlコマンドは、URLオブジェクトをネームスペースにバインドします。

オプション

次の表で、bindurlコマンドのオプションについて説明します。

オプション

説明

<objectname>

バインド先のオブジェクトの名前を指定します。

-help

ヘルプ・メッセージを指定します。

-describe

ツール操作を要約します。

-version

bindurlコマンドのバージョンを出力します。

-rebind

JNDI名がすでに存在する場合、このオプションを指定して、既存のJNDI名をこの新しいオブジェクトで上書きする必要があります。そうしない場合、このオプションでバインドは実行されません。

-grant <user|role>, <user|role>…

読取り権限および実行権限を<user>名と<role>名のシーケンスに付与します。再バインドする際には、読取り権限または実行権限を持つ既存のユーザーまたはロールを<user>名および<role>名で置き換えることができます。

-recursiveGrant <user|role>, <user|role>...

指定されたオブジェクトおよびオブジェクトが存在するすべてのコンテキストに、読取り許可および実行許可を再帰的に付与します。コンテキストの許可レベルがSYSの場合、そのコンテキストに対する付与は無視されます。

例

次の例では、URL文字列http://www.oracle.comがネームスペース内のURL参照/test/myURLにバインドされます。

bindurl /test/myURL http://www.oracle.com -rebind

-rebindオプションを使用して、/test/myURL参照がすでに存在しているかどうかを確認し、存在していれば文字列http://www.oracle.comで再バインドされます。

OJDSのAPIおよびクラス

この項では、OJDSの次のAPIおよびクラスについて説明します。

- oracle.aurora.jndi.ojds.OjdsClientContext

- oracle.aurora.jndi.ojds.OjdsServerContext

- oracle.aurora.jndi.ojds.OjdsInitialContextFactory

- oracle.aurora.jndi.ojds.OjdsURLContextFactory

- oracle.aurora.jndi.ojds.OjdsURLContext

oracle.aurora.jndi.ojds.OjdsClientContext

このクラスは、javax.naming.directory.DirContextインタフェースを実装します。データベースとの接続を確立し、OJDSをサポートするために必要なすべてのファンクションを実行します。次のメソッドを除いて、[DirContext]で説明されているすべてのメソッドがサポートされています。

- getSchema

- getSchemaClassDefintion

- modifyAttributes

- search

このクラスは、JAVA JDKベースのクライアントでInitialDirContextが作成されると自動的に作成されます。クライアント・アプリケーションとOJDSの間の通信およびオブジェクト・トランスポートを提供します。

接続を完了するには、次のJNDIプロパティを特定の値に設定する必要があります。

- java.naming.factory.initialをoracle.aurora.jndi.ojds.OjdsIntialContextFactoryに設定します。

- java.naming.security.principalを接続スキーマ名に設定します。

- java.naming.security.credentialsをスキーマ・パスワードに設定します。

- java.naming.provider.urlを有効なOJDS URLに設定します。

これらのプロパティは、次のコード・スニペットに示すように設定できます。

Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "oracle.aurora.jndi.ojds.OjdsInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "HR");
env.put(Context.SECURITY_CREDENTIALS, "<password>");
env.put(Context.PROVIDER_URL,"ojds://thin:localhost:5521:j3");

oracle.aurora.jndi.ojds.OjdsServerContext

このクラスは、javax.naming.directory.DirContextインタフェースを実装します。OJDS永続ストアとの通信には、内部データベース接続が使用されます。次のメソッドを除いて、[DirContext]で説明されているすべてのメソッドがサポートされています。

- getSchema

- getSchemaClassDefintion

- modifyAttributes

- search

このクラスは、データベース常駐アプリケーションでInitialDirContextが作成されると自動的に作成されます。OJDS永続ストアとの通信には、データベース内部のJDBCドライバが使用されます。

アプリケーションはloginスキーマとして実行されるため、OjdsClientContextではOjdsClientContextの4つの環境プロパティは無視されます。接続は、kprb [JDBC]内部ドライバを使用して行われます。Javaストアド・プロシージャでサーバー外部のアクセスが必要な場合は、java.naming.provider.urlプロパティの値として、「oracle.aurora.jndi.ojds.OjdsInitialContextFactory」で説明されているOJDS URLContextを使用する必要があります。

oracle.aurora.jndi.ojds.OjdsInitialContextFactory

このクラスは、javax.naming.spi.InitialContextFactoryインタフェースを実装します。JNDIのInitialContextまたはInitialDriContextクラスは、実行環境に応じてOjdsClientContextかOjdsServerContextのいずれかを作成します。

oracle.aurora.jndi.ojds.OjdsURLContextFactory

このクラスでは、OJDSスタイルのURLがサポートされます。URLに提供されたメソッドに応じて、このメソッドは、DirContextか、OJDSに格納されているオブジェクトのインスタンスを戻すことができます。

oracle.aurora.jndi.ojds.OjdsURLContext

このクラスは、oracle.aurora.jndi.ojds.OjdsClientContextの拡張です。OJDS URLからの接続情報の抽出と、OJDSへの接続の確立がサポートされています。oracle.aurora.jndi.ojds.OjdsClientContextクラスと同じインタフェースがサポートされます。

OjdsURLContextクラスを使用するには、次のパラメータを設定する必要があります。

- javax.naming.security.principalを接続スキーマに設定します。

- javax.naming.security.credentialsを接続スキーマのパスワードに設定します。

- javax.naming.factory.initialをoracle.aurora.jndi.ojds.OjdsInitialContextFactoryに設定します。

これらのプロパティは、次のコード・スニペットに示すように設定できます。

Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "oracle.aurora.jndi.ojds.OjdsInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "HR");
env.put(Context.SECURITY_CREDENTIALS, "<password>");
DirContext dir =
(new InitialContext(env)).lookup(”ojds://thin:localhost:5521:j3/public./mydir”);

脚注の凡例

脚注1: スラッシュ記号(\)

12 スキーマ・オブジェクトおよびOracle JVMユーティリティ

この章では、Oracle Database Java環境で使用するスキーマ・オブジェクトおよびOracle JVMユーティリティについて説明します。これらのユーティリティは、UNIXシェルまたはMicrosoft社のWindowsのDOSプロンプトから実行します。

注意:
ツールに指定されている名前は、すべて大/小文字の区別があります。このため、スキーマ、ユーザー名およびパスワードは大文字に変換されません。

この章の内容は、次のとおりです。

- スキーマ・オブジェクトの概要

- ロード内容とロード時期

- スキーマ・オブジェクトの解決

- スキーマ・オブジェクトのコンパイル

- ojvmtcツール

- loadjavaツール

- dropjavaツール

- ojvmjavaツール

スキーマ・オブジェクトの概要

従来のJava仮想マシン(JVM)では、Javaファイルをコンパイルおよびロードしていましたが、Oracle JVMではスキーマ・オブジェクトをコンパイルおよびロードします。次の種類のJavaスキーマ・オブジェクトがロードされます。

- Javaクラス・スキーマ・オブジェクト(Javaクラス・ファイルに相当)。

- Javaソース・スキーマ・オブジェクト(Javaソース・ファイルに相当)。

- Javaリソース・スキーマ・オブジェクト(Javaリソース・ファイルに相当)。

クラス・ファイルをOracle JVMで実行可能にするには、loadjavaツールを使用して、クラス・ファイルまたはソース・ファイルからJavaクラス・スキーマ・オブジェクトを作成し、スキーマにロードする必要があります。リソース・ファイルをOracle JVMからアクセス可能にするには、loadjavaツールを使用して、リソース・ファイルからJavaリソース・スキーマ・オブジェクトを作成して、ロードします。

dropjavaツールは、Javaファイルに対応するスキーマ・オブジェクトを削除します。loadjavaツールで作成したJavaスキーマ・オブジェクトは、必ずdropjavaツールを使用して削除してください。SQLのデータ定義言語(DDL)コマンドを使用してスキーマ・オブジェクトを削除した場合、loadjavaツールおよびdropjavaツールで保持している補助データは更新されません。

ロード内容とロード時期

リソース・ファイルは、必ずloadjavaツールを使用してロードする必要があります。データベースの外で従来のコンパイラを使用して.classファイルを作成する場合、そのファイルは、loadjavaツールを使用してロードする必要があります。クラス・ファイルをロードする別の方法には、ソース・ファイルをロードし、Oracle Databaseで、結果のクラス・スキーマ・オブジェクトをコンパイルおよび管理する方法があります。Oracle Database 12cリリース1 (12.1)では、ほとんどのコードをデータベースの外でコンパイルおよびデバッグしてから、.classファイルをロードするのが最も能率的な方法です。特定のJavaクラスに対して、.classファイルまたは対応する.javaファイルのいずれかをロードできますが、両方はロードできません。

loadjavaツールは、ソース・ファイルとリソース・ファイル、またはクラス・ファイルとリソース・ファイルのいずれかを含むJavaアーカイブ(JAR)ファイルを受け入れます。loadjavaツールにJARファイルまたはZIPファイルを渡すと、デフォルトで、アーカイブをオープンし、そのメンバーを個別にロードします。

注意:
データベースにJARの内容をロードする場合、JAR自体を表すデータベース・オブジェクトを作成するオプションが用意されています。詳細は、「データベース常駐JAR」を参照してください。

前回のロード時から変更されていないファイルは、再ロードされません。このため、JARファイルのロードによるパフォーマンスの低下はほとんどありません。JARファイルのロードは、loadjavaツールの簡単で安全な使用方法です。

同一スキーマ内の2つのスキーマ・オブジェクトに同じクラスを定義することはできません。たとえば、a.javaでクラスxを定義し、xの定義をb.javaに移動する場合を考えてみます。a.javaがすでにロードされている場合、loadjavaツールはb.javaのロードを拒否します。かわりに、次のいずれかの方法を実行する必要があります。

- a.javaを削除し、b.javaをロードして、次に新しいa.java(xは定義されていません)をロードします。

- 新しいa.java(xは定義されていません)をロードし、次にb.javaをロードします。

スキーマ・オブジェクトの解決

すべてのJavaクラスには、他のクラスへの参照が含まれています。従来のJVMは、CLASSPATHで指定されたディレクトリ、ZIPファイルおよびJARファイル内でクラスを検索します。一方、Oracle JVMはスキーマでクラス・スキーマ・オブジェクトを検索します。データベース内のクラスごとにリゾルバ仕様があり、これは、CLASSPATHに相当するOracle Databaseの仕様です。たとえば、alphaというクラスのリゾルバ仕様は、alphaで使用するクラスを検索するスキーマをリストします。リゾルバ仕様はクラスごとにあるのに対し、従来のJVMのCLASSPATHはすべてのクラスを対象にしたグローバルな仕様であることに注意してください。

各クラス・スキーマ・オブジェクトには、リゾルバ仕様の他に、クラス間参照バインドのリストがあります。参照リストの各項目の内容は、別のクラスへの参照と次のいずれかです。

- クラスで参照を使用するときにコールするクラス・スキーマ・オブジェクトの名前

- 参照が未解決かどうかを示すコード、つまり、対象のスキーマ・オブジェクトが認識されているかどうかを示すコード

参照リストの保守は、Oracle Databaseの機能の1つであるリゾルバが行います。クラス内のクラス間参照ごとに、リゾルバは、クラスのリゾルバ仕様で指定されたスキーマで、参照を満たす有効なクラス・スキーマ・オブジェクトを検索します。すべての参照が解決されると、リゾルバによりこのクラスは「有効」とマークされます。解決処理が行われていないクラス、または正常に解決できなかったクラスは「無効」とマークされます。無効になったスキーマ・オブジェクトに依存しているクラスも、最初のクラスが無効とマークされるときに無効とマークされます。つまり、無効化は1つのクラスからそのクラスを使用しているクラス群、そのクラス群を使用しているクラス群というように、上方に連鎖します。無効なクラスに依存するクラスを解決するとき、リゾルバは最初に参照先クラスを解決しようとします。これは、単に解決処理が行われていないために、無効とマークされている場合があるためです。リゾルバは、有効とマークされているクラスを解決しません。

開発者は、loadjavaツールでクラスを解決するように指示することができ、実行時まで解決を延期することもできます。無効とマークされているクラスを別のクラスでロードしようとすると、自動的にリゾルバが実行されます。実行時以前に解決すると、欠落しているクラスを早期に検出できます。実行時に解決できない場合は、ClassNotFound例外が生成されます。また、次の理由で実行時に解決できない場合があります。

- データベース・リソースの不足(クラスのツリーが非常に大きい場合)

- 循環依存が原因のデッドロック

loadjavaツールには、次の2つの解決モードがあります。

- Load-and-resolve
-resolveオプションを指定して、コマンドラインで指定したすべてのクラスをロードし、無効とマークしてからクラスを解決します。相互に参照しているクラス群を初めてロードするときは、このモードを使用し、通常は、孤立したクラスを再ロードするときもこのモードを使用します。このモードでは、すべてのクラスをロードしてから解決することによって、この後でクラスの参照先クラスがコマンドの実行中にロードされる場合でも、エラー・メッセージの発生を回避できます。

- Load-then-resolve
このモードでは、実行時に各クラスを解決します。-resolveオプションは指定しません。

注意:
Javaコンパイラと同様に、loadjavaツールはクラスへの参照を解決しますが、リソースへの参照は解決しません。したがって、クラスに必要なリソース・ファイルを正しくロードする必要があります。

可能な場合は、すべてのクラスのロードが完了するまで、解決を延期してください。延期することによって、使用するクラスがロードされていないために、リゾルバによりそのクラスが無効とマークされるのを回避できます。

スキーマ・オブジェクトのコンパイル

ソース・ファイルをロードすると、Javaソース・スキーマ・オブジェクトが作成または更新され、そのソースから以前に導出されたクラス・スキーマ・オブジェクトが無効になります。クラス・スキーマ・オブジェクトが存在しない場合は、loadjavaツールによって作成されます。古いクラス・スキーマ・オブジェクトは新しくロードしたソースからコンパイルされていないため、loadjavaは古いクラス・スキーマ・オブジェクトを無効にします。新しくロードしたソース(たとえば、クラスA)のコンパイルは、次のいずれかの条件で自動的に実行されます。

- リゾルバが、クラスBの処理時に、クラスBの参照先クラスAが無効であることを検出した場合。

- コンパイラが、クラスBのソースのコンパイル時に、クラスBの参照先クラスAが無効であることを検出した場合。

- クラス・ローダーが、実行対象のクラスAのロード時に、クラスAが無効であることを検出した場合。

ソース・ファイルのロード時に強制的にコンパイルするには、loadjava -resolveオプションを使用します。

コンパイラはエラー・メッセージを事前定義のUSER_ERRORSビューに書き込みます。つまり、loadjavaツールは、コンパイラの起動によって作成されたメッセージを取得して表示します。

コンパイラはいくつかのオプションを認識します。コンパイラにオプションを指定するには、次の2つの方法があります。-resolveオプションを指定してloadjavaツールを実行した場合は、コマンドラインでコンパイラ・オプションを指定できます。さらに、スキーマごとのデータベース表JAVA$OPTIONSに永続的なコンパイラ・オプションを指定できます。JAVA$OPTIONS表は、loadjavaツールのオプションを使用して選択的にオーバーライドできる、デフォルトのコンパイラ・オプションに使用できます。

注意:
コマンドライン・オプションによって、JAVA$OPTIONS表内の一致しているエントリがオーバーライドおよび消去されます。

JAVA$OPTIONSの行には、オプションの設定を適用するソース・スキーマ・オブジェクトの名前が指定されています。複数行を使用すると、ソース・スキーマ・オブジェクトごとに異なるオプションを設定できます。クラス・ローダーによってコンパイラをコールするか、またはコマンドラインでオプションを指定せずにコンパイラをコールすると、コンパイラはJAVA$OPTIONSでオプションを検索します。コンパイル対象のソース・スキーマ・オブジェクトにJAVA$OPTIONS表のエントリもコマンドラインのオプション値もない場合、コンパイラは次のデフォルト値を使用します。

- encoding = System.getProperty("file.encoding");

- online = true
このオプションは、SQLJ構文が含まれているJavaソースにのみ適用されます。

- debug = true
このオプションはjavac -gと同じです。

関連項目:
「データベース表に指定されるコンパイラ・オプション」

ojvmtcツール

ojvmtcツールを使用すると、loadjavaツールの実行前にすべての外部参照を解決できます。ojvmtcツールでは、クラス参照の解決に使用する、JAR、クラスまたはディレクトリを指定するクラスパスの仕様が許可されます。外部参照を解決できない場合、指定したオプションに応じて、このツールは未解決の参照または生成されたスタブ・クラスのリストを作成して参照を解決できるようにします。生成されたスタブ・クラスは、実行時に参照される場合、java.lang.ClassNotfoundExceptionをスローします。

構文は次のとおりです。

ojvmtc [-help ] [-bootclasspath] [-server connect_string] [-jar jar_name] [-list] -classpath jar1:path2:jar2
jars,...,classes

次に例を示します。

ojvmtc -bootclasspath $JAVA_HOME/jre/lib/rt.jar -classpath classdir/lib1.jar:classdir/lib2.jar -jar set.jar app.jar

この例では、rt.jar、classdir/lib1.jarおよびclassdir/lib2.jarを使用して、app.jarの参照を解決します。rt.jarにあるクラスを除き、調査対象のクラスはすべてset.jarに追加されます。

次に、別の例を示します。

ojvmtc -server thin:HR/@localhost:5521:orcl -classpath jar1:jar2 -list app2.jar
Password:password

この例では、接続文字列で指定されたサーバーにあるクラスと、jar1およびjar2を使用して、app2.jarを解決します。欠落している参照がすべてstdoutに表示されます。

表12-1は、このコマンドの引数の一覧です。

表12-1 ojvmtcの引数の概要

引数

説明

-classpath

クロージャ・セットの指定のJARおよびクラスを使用します。

-bootclasspath

クロージャの指定のクラスを使用します。ただし、クロージャ・セットにこれらのクラスを含めません。

-server connect_string

-bootclasspathと同じ方法で表示クラスを使用してサーバーに接続します。

connect_string thin|OCI

特定のThinドライバまたはOracle Call Interface(OCI)ドライバを使用してサーバーに接続します。

Thinドライバを使用する場合、構文は次のようになります。

thin:user/passwd@host:port:sid

OCIドライバを使用する場合、構文は次のようになります。

oci:user/passwd@host:port:sid
oci:user/passwd@tnsname
oci:user/passwd@(connect descriptor)

-jar jar_name

クロージャ・セットの各クラスをJARに書き込み、欠落しているクラスのスタブを生成します。

-list

欠落しているクラスの一覧を作成します。

loadjavaツール

loadjavaツールは、ファイルからスキーマ・オブジェクトを生成してスキーマにロードします。スキーマ・オブジェクトはJavaソース、クラスおよびデータファイルから作成できます。また、loadjavaツールでは、SQLJファイルからもスキーマ・オブジェクトを作成できます。

クラスをロードするには、次のSQLデータベース権限が必要です。

- スキーマにロードする場合はCREATE PROCEDUREおよびCREATE TABLE権限。

- 別のスキーマにロードする場合はCREATE ANY PROCEDUREおよびCREATE ANY TABLE権限。

- oracle.aurora.security.JServerPermission.loadLibraryInClass.classname。

loadjavaツールは、コマンドラインから実行するか、またはDBMS_JAVAクラスに含まれるloadjavaメソッドを使用して実行できます。使用しているJavaアプリケーション内からこのツールを実行する方法は、次のとおりです。

call dbms_java.loadjava('... options...');

オプションは、loadjavaツールのコマンドラインで指定できるオプションと同じです。各オプションは空白で区切ります。オプションをカンマで区切らないでください。ただし、空白を含む-resolverオプションは例外です。-resolverの場合は、次に示すように、他のすべてのオプションを最初の入力パラメータで指定し、-resolverオプションは2番目のパラメータで指定します。

call dbms_java.loadjava('..options...', 'resolver_options');

-thin、-oci、-userおよび-passwordの各オプションは、loadjavaコマンドライン・ツールのデータベース接続に関連しているため、指定しないでください。出力はstderrに送信されます。serveroutputをオンに設定し、必要に応じてdbms_java.set_outputをコールします。

注意:
loadjavaツールは、$ORACLE_HOMEの下のbinディレクトリに格納されています。

loadjavaツールは、終了直前に、正常に処理されたかどうかをチェックします。発生したすべての障害は、次のヘッダーの後に要約が示されます。

The following operations failed

データベースへの接続が失われるなど、条件によっては、loadjavaツールが完了前に停止する場合があります。エラーは次の構文で表示されます。

exiting: error_reason

この項の内容は、次のとおりです。

- 構文

- 引数の概要

- 引数の詳細

構文

loadjavaツールのコマンド構文は次のとおりです。

注意:

- クラス参照の解決では、-genmissingオプションおよび-genmissingjarオプションよりも、(* -)オプションが推奨されます。(* -)オプションの詳細は、「存在しないクラスへの参照の許可」を参照してください。

- -genmissingオプションおよび-genmissingjarオプションは、オプション・ファイルまたはオプション表では使用できません。これらのオプションは、すべてのクラスのロードには適用可能で、特定のクラスにのみ使用することはできません。

loadjava {-user | -u} user [@database] [options]
file.java | file.class | file.jar | file.zip |
file.sqlj | resourcefile | URL...
[-casesensitivepub]
[-cleargrants]
[-debug]
[-d | -definer]
[-dirprefix prefix]
[-e | -encoding encoding_scheme]
[-fileout file]
[-f | -force]
[-genmissing]
[-genmissingjar jar_file]
[-g | -grant user [, user]...]
[-help]
[-jarasresource]
[-noaction]
[-nosynonym]
[-nousage]
[-noverify]
[-o | -oci | oci8]
[-optionfile file]
[-optiontable table_name]
[-publish package]
[-pubmain number]
[-recursivejars]
[-r | -resolve]
[-R | -resolver "resolver_spec"]
[-resolveonly]
[-S | -schema schema]
[-stdout]
[-stoponerror]
[-s | -synonym]
[-tableschema schema]
[-t | -thin]
[-unresolvedok]
[-v | -verbose]
[-jarsasdbobjects]
[-prependjarnames]
[-nativecompile]

引数の概要

表12-2は、loadjavaツールのコマンド引数の一覧です。オプションを変えて同じファイルを指定して複数回loadjavaツールを実行すると、最後の起動時に指定したオプションが保持されます。ただし、次の2つの例外があります。

- ダイジェスト表のエントリに一致しているためにloadjavaツールによってファイルがロードされない場合は、コマンドラインで指定した大半のオプションがスキーマ・オブジェクトに反映されません。例外は-grantと-resolveで、これらのオプションは必ず反映されます。loadjavaツールでダイジェスト表の参照をスキップするように指示するには、-forceオプションを使用する必要があります。

- -grantオプションは累積です。特定スキーマの特定クラスに対して起動されたすべてのloadjavaツールに指定されているユーザーには、EXECUTE権限が付与されます。

表12-2 loadjavaの引数の概要

引数

説明

filenames

.java、.class、.sqlj、.ser、.jar、.zipおよびリソース・ファイル名の引数を、必要な数だけ任意の順序で組み合せて指定できます。

-proxy host:port

クラス、リソースおよびJavaソースをロードするために、サーバー・ホストまたはloadjavaクライアントに物理的にアクセスできない場合、loadjavaツールでHTTP URLを使用して、JAR、クラス・ファイルまたはリソースを指定し、リモート・サーバーからクラスをロードできます。hostはホスト名またはアドレス、portはプロキシ・サーバーが使用するポートです。ロードするファイルのタイプ(JAR、クラス、リソースまたはJavaソース)をloadjavaツールで決定できるようにURLを実装する必要があります。次に例を示します。

loadjava –u HR –r –v –proxy proxy_server:1020 http://my.server.com/this/is /the/path/my.jar
Password: password

URLサポートがサーバー内で使用される場合、リモート・ソースにアクセスするための適切なJavaパーミッションが必要です。ftp:やfile:などのURLもサポートされます。

-casesensitivepub

公開時に、大/小文字の区別がある名前が作成されます。名前がすべて大文字でないかぎり、通常、PL/SQLでは名前を引用符で囲む必要があります。

-cleargrants

-grantオプションを指定すると、loadjavaツールはクラス、ソースおよびリソースにEXECUTE権限を付与します。ただし、権限の取消しは行いません。-cleargrantsを指定すると、loadjavaツールは、-grantオペランドで指定されたユーザーとロールに実行権限を付与する前に、すでに付与されているすべての実行権限を取り消します。たとえば、実行権限をHRのみに付与する場合、適切なオプションは次のようになります。

-grant HR -cleargrants

-debug

SQLロギングをオンにします。

-definer

デフォルトでは、クラス・スキーマ・オブジェクトはその実行者の権限で実行されます。このオプションは、定義者の権限をクラスに付与します。このオプションは、UNIXのsetuid機能に概念的に類似しています。

-dirprefix prefix

prefixで始まるファイルまたはJARエントリの場合は、スキーマ・オブジェクトの名前が決定する前に、このprefixが名前から削除されます。クラスとソースの場合、スキーマ・オブジェクトの名前はその内容によって決定されます。したがって、リソースのみがこのオプションの影響を受けます。

-encoding

コンパイラのためにソース・ファイルのエンコーディングを識別し、JAVA$OPTIONS表に一致する値がある場合はオーバーライドします。値は、javac -encodingオプションの値と同じです。コマンドラインまたはJAVA$OPTIONS表でエンコーディングを指定しない場合は、次のコードから戻される値がエンコーディング値とみなされます。

System.getProperty("file.encoding");

このオプションはソース・ファイルのロード時のみ有効です。

-fileout file

すべてのメッセージを指定のファイルに表示します。

-force

ダイジェスト表のエントリに一致する場合でも、ファイルが強制的にロードされます。

-genmissing

loadjavaツールの処理対象のクラスが参照するクラスとメソッドを判別します。データベースまたはファイル引数に存在しないクラスを欠落しているクラスと呼びます。このオプションは、欠落しているクラスに対して、参照対象のすべてのメソッドが含まれるダミーの定義を生成します。次に、生成されたクラスをデータベースにロードします。この処理は、クラスの解決の前に実行されます。

参照をソースから検出することは、参照をクラス・ファイルから検出するよりも困難であり、通常、ライブラリの配布にソースは使用しないため、loadjavaツールはこの処理をソース・ファイルに対して実行しません。

欠落しているクラスがロードされるスキーマは、参照元クラスが他のスキーマで作成された場合でも、-userオプションで指定されたスキーマになります。作成されたクラスにはフラグが設定されるため、複数のツールで認識できます。これは特に、検証機能が生成されたクラスを認識するために必要です。

-genmissingjar jar_file

このオプションは、-genmissingと同じアクションを実行します。さらに、生成されたすべてのクラスの定義が含まれるjar_fileというJARファイルを作成します。

-grant

ロードされたクラスに対するEXECUTE権限を、リスト中のユーザーに付与します。ユーザー名は、空白ではなくカンマで区切って、必要な数だけ任意の順序で組み合せて指定できます。

EXECUTE権限を別のスキーマのオブジェクトに付与するには、WITH GRANTオプションを使用して元のCREATE PROCEDURE権限が付与されている必要があります。

注意:

- -grantは累積のオプションです。ユーザーはEXECUTE権限を持つユーザーのリストに追加されます。権限を削除するには、-cleargrantsオプションを使用します。

- スキーマ名は必ず大文字で指定します。

-help

loadjavaツールとそのオプションの使用方法に関するメッセージを表示します。

-jarasresource

JARファイルを解凍してその中の各クラスをロードするかわりに、JARファイル全体をリソースとしてスキーマにロードします。脚注1

-noaction

ファイルに対してアクションを実行しません。これには、スキーマ・オブジェクトの作成、実行パーミッションの付与などのアクションが含まれます。このオプションは、通常、特定のクラスがJARファイルに作成されるのを抑制するために、オプション・ファイル内で使用します。コマンドラインで使用すると、オプション・ファイルでオーバーライドされないかぎり、loadjavaツールはすべてのファイルを無視します。ただし、JARファイルは検査の対象で、ファイル内にMETA-INF/loadjava-optionsエントリがあるかどうかが判別されます。エントリがある場合は、オプション・ファイルが処理されます。オプション・ファイル内の-actionオプションは、コマンドラインで指定された-noactionオプションをオーバーライドします。

-norecursivejars

他のJARファイルに含まれているJARファイルをリソースとして処理します。これはデフォルトの動作です。このオプションは、-recursivejarsオプションをオーバーライドするために使用します。

-nosynonym

クラスのPUBLICシノニムを作成しません。これはデフォルトの動作です。このオプションは、-synonymオプションをオーバーライドします。

-nousage

オプションが指定されていない場合、または-helpオプションが指定されている場合は、使用方法についての指定のメッセージを抑制します。

-noverify

クラスがバイトコードの検証なしにロードされます。このオプションを使用するには、oracle.aurora.security.JServerPermission(Verifier)を付与されていることが必要です。このオプションを効果的にするには、-resolveと併用する必要があります。

-oci | -oci8

loadjavaツールに対して、JDBC Oracle Call Interface (OCI)ドライバを使用してデータベースと通信するように指示します。-ociと-thinは相互に排他的です。いずれも指定しない場合は、デフォルトで-ociが使用されます。-ociを選択すると、-user値の構文が暗黙的に使用されます。URLの指定は必要ありません。

-optionfile file

loadjavaオプションでファイルを指定できます。

-optiontable tablename

このオプションは、パターンおよびオプションのソースがファイルではなくSQL表であること以外は、-optionfileに類似しています。

-publish package

packageは、loadjavaツールによって作成または置換されます。このパッケージには、適格なメソッドのラッパーが定義されます。オプション・ファイルを使用すると、loadjavaツールの1回の起動で複数のパッケージを作成できます。各パッケージでは、メソッドと同じ名前変換が実行されます。

-pubmain number

java.lang.String[]型の単一の引数を取るメソッドに適用される特殊なケースです。SQLプロシージャまたはファンクションの複数の異体が作成され、それぞれが異なる数のVARCHAR型の引数を取ります。特に、最大でnumberの数まで引数を取る異体が作成されます。デフォルト値は3です。このオプションは、java.lang.String[]型の単一の引数を取るメソッドのほか、mainにも適用されます。

-recursivejars

通常、loadjavaツールはJARファイル内で.jar拡張子を持つエントリを検出すると、そのエントリをリソースとしてロードします。このオプションを指定すると、loadjavaツールは、該当するJARファイルをトップレベルのJARファイルと同様に処理します。つまり、エントリを読み取り、クラス、ソースおよびリソースをロードします。

-resolve

コマンドラインのすべてのクラスがロードされた後に、必要に応じて、クラス内の外部参照をコンパイルおよび解決します。-resolveオプションを指定しないと、loadjavaツールはファイルをロードしますが、コンパイルまたは解決を実行しません。

-resolver

新しくロードされたクラスにバインドされる、明示的なリゾルバ仕様を指定します。-resolverを指定しないと、カレント・ユーザーのスキーマとPUBLICを含んだデフォルトのリゾルバ仕様が使用されます。

-resolveonly

loadjavaツールで最初の作成手順をスキップします。権限付与、解決、シノニムの作成などは実行されます。

-schema

スキーマ・オブジェクトを作成するスキーマを指定します。このオプションを指定しないと、-userのスキーマが使用されます。自分のスキーマ以外にスキーマ・オブジェクトを作成するには、次の権限が必要です。

- CREATE TABLEまたはCREATE ANY TABLE

- CREATE INDEXまたはCREATE ANY INDEX

- SELECT ANY TABLE

- UPDATE ANY TABLE

- INSERT ANY TABLE

- DELETE ANY TABLE

- CREATE PROCEDUREまたはCREATE ANY PROCEDURE

- ALTER ANY PROCEDURE

さらに、クラスに対するJServerPermission loadLibraryInClassも必要です。

注意: 前述の権限を付与すると、SYSスキーマ以外のすべてのスキーマでの表の作成および操作が可能になります。セキュリティ上の理由から、これらの設定は十分に注意して使用することをお薦めします。

-stdout

stderrではなく、stdoutに出力を送信します。

-stoponerror

通常、loadjavaツールでは、ファイルの処理中にエラーが発生した場合、メッセージを発行して他のクラスの処理を継続します。このオプションを指定すると、エラーの発生時に処理を停止します。さらに、Javaオブジェクトに適用され、クラスのロード先スキーマのUSER_ERROR表に格納されているすべてのエラーをレポートします。ただし、ORA-29524エラーはレポートしません。このエラーは、参照先のクラスが解決できないため、クラスを解決できない場合に生成されます。したがって、このエラーは、参照先のクラスが未解決であるために起こった、二次的な結果になります。

-synonym

ロードされるクラスに対してPUBLICシノニムを作成し、ロード先スキーマの外側からもクラスにアクセスできるようにします。このオプションを指定するには、CREATE PUBLIC SYNONYM権限が必要です。ソース・ファイルに対して-synonymを指定すると、そのソース・ファイルからコンパイルされたクラスは、-synonymを指定してロードした場合と同様に処理されます。

-tableschema schema

Javaファイルの接続先スキーマではなく、指定したスキーマ内にloadjavaツールの内部表を作成します。

-thin

loadjavaツールに対して、JDBC Thinドライバを使用してデータベースと通信するように指示します。-thinを選択すると、-user値の構文が暗黙的に使用されます。-userオプションを使用して、適切なURLを指定する必要があります。

-unresolvedok

-resolveと組み合せると、未解決のエラーが無視されます。

-user

ユーザー名、パスワードおよびデータベース接続文字列を指定します。ファイルはこのデータベース・インスタンスにロードされます。

-verbose

loadjavaツールに対して、実行中に詳細なステータス・メッセージを表示するように指示します。-verboseオプションを使用して、ダイジェスト表のエントリに一致したためにloadjavaツールがファイルをロードしなかった場合を調べます。

-jarsasdbobjects

現在のloadjavaツール・コマンドで処理されるJARがデータベース常駐JARとしてデータベースに格納されることを示します。脚注2

-prependjarnames

-jarsasdbobjectsオプションと一緒に使用します。このオプションにより、異なるJARの同じ名前のクラスが同じスキーマ内で共存できます。これを行うには、クラス名の先頭にJARの名前のバージョンを追加して、データベース・オブジェクトの一意の名前を生成します。

脚注1この方法でJARファイルをロードする場合、これを解決や実行に使用することはできません。

脚注2この方法でJARファイルをロードする場合、これを解決や実行に使用できます。

引数の詳細

この項では、動作が複雑なloadjavaツールの一部の引数について、表12-2の概要よりさらに詳しく説明します。

ファイル名

.class、.java、.sqlj、.jar、.zipおよびリソース・ファイルは、必要な数だけ任意の順序で指定できます。JARファイルまたはZIPファイルを指定すると、loadjavaツールは、そのJARまたはZIPでファイルを処理します。JARまたはZIPのスキーマ・オブジェクトはありません。JARまたはZIPに別のJARまたはZIPが含まれていると、loadjavaツールはこれらのファイルを処理しません。

ファイルのロード方法としては、JARまたはZIPにファイルをまとめ、アーカイブとしてロードすることをお薦めします。アーカイブをロードすることで、リソース・スキーマ・オブジェクトのネーミングの手間を省くことができます。Java Development Kit (JDK)で使用するJARまたはZIPがある場合も、loadjavaツールでロードでき、この場合、リソース・スキーマ・オブジェクトのネーミングについては知る必要がありません。

スキーマ・オブジェクト名はファイル名とは異なり、loadjavaツールは異なるタイプのスキーマ・オブジェクトを異なる方法でネーミングします。クラス・ファイルは自己識別できるため、loadjavaツールによるクラス・ファイル名のスキーマ・オブジェクト名へのマッピングは開発者には表示されません。ソース・ファイル名のマッピングも開発者には表示されません。loadjavaツールは、ファイル内に定義されている最初のクラスの完全修飾名をスキーマ・オブジェクト名とします。JARファイルとZIPファイルにも、それぞれのファイルの名前が含まれています。

ただし、リソース・ファイルは自己認識できません。loadjavaツールは、引数で指定したとおりのリテラルなファイル名からJavaリソース・スキーマ・オブジェクト名を生成します。リソース・スキーマ・オブジェクトがクラスで使用され、リソースの正しい指定方法がわかりにくい場合があるため、コマンドラインで正しくリソース・ファイル名を指定することが重要です。

各リソース・ファイルを正確にロードする最善の方法は、パッケージ・ツリーの最上部からloadjavaツールを実行し、そのディレクトリに相対するリソース・ファイル名を指定する方法です。

注意:
パッケージ・ツリーの最上部とは、CLASSPATHで指定するディレクトリです。

この規則に従わない場合は、次のリソース・ファイル・ネーミングに従ってください。リソース・ファイルをロードすると、loadjavaツールはコマンドラインで指定したとおりのリテラルなリソース・ファイル名からリソース・スキーマ・オブジェクト名を生成します。たとえば、次のように入力したとします。

% cd /home/HR/javastuff
% loadjava options alpha/beta/x.properties
% loadjava options /home/HR/javastuff/alpha/beta/x.properties

同じファイルを相対パス名と絶対パス名で指定していますが、loadjavaツールはalpha/beta/x.propertiesとROOT/home/HR/javastuff/alpha/beta/x.propertiesの2つのスキーマ・オブジェクトを作成します。リソース・スキーマ・オブジェクトの名前は、入力したとおりのファイル名から生成されます。

クラスは、リソース・ファイルを相対的に参照することも絶対的に参照することもできます。loadjavaツールとクラス・ローダーで同じスキーマ・オブジェクト名を使用するには、クラスからgetResource()またはgetResourceAsString()に渡す名前をコマンドラインに入力します。

リソース・ファイルは、次のようにJARでロードできます。この場合、名前をコマンドラインに正しく入力するために、クラスで使用するリソース名が相対名か絶対名かを記憶したり、ディレクトリを変更する必要はありません。

% cd /home/HR/javastuff
% jar -cf alpharesources.jar alpha/*.properties
% loadjava options alpharesources.jar

処理をさらに簡略化するには、クラス・ファイルとリソース・ファイルの両方をJARで格納します。これによって、次のコマンドを起動しても同じ処理を実行できます。

% loadjava options alpha.jar
% loadjava options /home/HR/javastuff/alpha.jar

前述したloadjavaツール・コマンドは、JARファイルの内容をロードするには任意のパス名が使用できることを示しています。冗長なコマンドを実行した場合でも、loadjavaツールは、ファイルを2回ロードする必要がないことをダイジェスト表を通じて認識します。したがって、loadjavaツールの前回の起動後に変更されたファイルが少ない場合でも、JARファイルの再ロードには、考えられているほどの時間はかかりません。

definer

{-definer | -d}

このオプションはストアド・プロシージャにおける定義者権限に相当し、概念的にはUNIXのsetuid機能に類似しています。ただし、setuidはプログラム全体に適用されますが、-definerオプションは各クラスに適用できます。さらに、定義者ごとに異なる権限を付与することもできます。アプリケーションは多数のクラスで構成される場合があるため、意図した結果を得るには、-definerを注意して適用する必要があります。つまり、クラスに必要以上の権限を付与しないように注意してください。

関連項目:
「現行ユーザーの制御」

noverify

[-noverify]

このオプションを指定すると、クラスがバイトコードの検証なしにロードされます。このオプションを実行するには、oracle.aurora.security.JServerPermission(Verifier)を付与されていることが必要です。また、このオプションは、-resolveと併用する必要があります。

検証機能によって、形式が無効なJavaバイナリがサーバーにロードされて実行されるのを防止できます。ロードするJARまたはクラスが有効であることが判明している場合は、このオプションによってloadjavaツールの関連プロセスを高速化できます。検証プロセス時には、解析のパフォーマンスを向上させるためのOracle Database固有の最適化が実行されます。したがって、このオプションを使用すると、アプリケーションの解析のパフォーマンスが低下する場合があります。

optionfile

[-optionfile <file>]

このオプションを使用すると、loadjavaツールで指定できる各種オプションにファイルを指定できます。このファイルは、他のloadjavaツール・オプションが処理される前に、loadjavaツールで読み取られて処理されます。このファイルには1行以上が含まれ、各行にはパターンと一連のオプションが含まれます。各行は、改行文字(\n)で終了している必要があります。

loadjavaツールで処理されるファイルまたはJARエントリごとに、作成されるスキーマ・オブジェクトのロング名がパターンと照合してチェックされます。パターンは、任意の文字列を示すワイルドカード(*)で終了している場合があり、使用しない場合、パターンは名前と完全に一致する必要があります。

一致するJavaスキーマ・オブジェクトに適用されるオプションは、行の後半で指定します。オプションは、コマンドライン・オプションを置換するのではなく、コマンドライン・オプションに追加されます。複数の行が名前と一致する場合、一致する行はパターンの長さが短い順にソートされ、各行のオプションが追加されます。通常、loadjavaツール・オプションは累積ではありません。後から追加されたオプションは以前のオプションをオーバーライドします。つまり、長いパターンで行に指定されたオプションは、短いパターンで行に指定されたオプションをオーバーライドします。

このファイルは、java.io.StreamTokenizerで解析されます。

このファイルでJavaのコメントを使用できます。行のコメントは#で開始します。空の行は無視されます。引用文字には二重引用符(")を使用してください。つまり、空白を含むオプションは、二重引用符で囲む必要があります。-userや-verboseなどの特定のオプションは、loadjavaツールの処理全体に影響を与えますが、個別のJavaスキーマ・オブジェクトに対して実行されるアクションには影響を与えません。このようなオプションがオプション・ファイルに存在する場合は無視されます。

アプリケーションをパッケージ化するために、loadjavaツールは処理対象の各JARファイルでMETA-INF/loadjava-optionsエントリを検索します。このエントリが検出された場合、そのエントリは、JARファイル内の他のすべてのエントリに適用されるオプション・ファイルとして処理されます。ただし、loadjavaツールは、JARファイルで出現する順にエントリに対する処理を実行します。

loadjavaツールがMETA-INF/loadjava-optionsを処理する前にエントリを部分的に処理した場合、適用可能なオプションに準拠するようにスキーマ・オブジェクトの変更を試みます。たとえば、loadjavaツールは、定義者権限で作成される必要があったクラスが実行者権限で作成された場合に、そのクラスを変更します。-noactionに対する修正は、作成済のスキーマ・オブジェクトを削除することです。loadjavaツールの起動前にスキーマ・オブジェクトが存在していた場合にそれが削除されることを除き、これによって正しい結果が得られます。

optiontable

[-optiontable table_name]

このオプションでは、クラスのプロパティを永続的に指定できます。表をロードする機構はありません。表名には、3つの文字型の列、PATTERN、OPTIONおよびVALUEを含める必要があります。PATTERNの値は、オプション・ファイルのパターンと同様に解釈されます。他の2つの列は、対応するコマンドライン・オプションで、オペランドを取ります。たとえば、次のコマンドを使用して表FOOを作成するとします。

create table foo (pattern varchar2(2000), option_name varchar2(2000), value varchar2(2000));

この場合、optiontableオプションを次のように使用できます。

loadjava -optiontable foo myjar.jar

オペランドを取らないオプションの場合はVALUE列をNULLにします。表の行は、オプション・ファイルの行と同様に処理されます。特定のスキーマ・オブジェクトのオプションを決定するために行が検査され、一致するとそのオプションがオプション・リストに追加されます。2つの行に、-synonymと-nosynonymなど、同じパターンだが矛盾するオプションがある場合、どちらが優先されるかは不明です。2つの行のパターン列とオプション列が同じである場合、どちらのVALUEが優先されるかは不明です。

publish

[-publish <package>]
[-pubmain <number>]

公開オプションを使用すると、loadjavaツールは処理済のクラスに含まれるメソッドのPL/SQLラッパーを作成します。通常、ユーザーは、JAR内にあるいくつかのクラスのラッパーのみを公開します。このオプションは、オプション・ファイルで指定されている場合に最も役立ちます。

公開可能にするには、メソッドが次の条件を満たす必要があります。

- メソッドがpublicクラスのメンバーであることが必要です。

- メソッドをpublicおよびstaticとして宣言する必要があります。

- メソッドのシグネチャは、次の規則を満たしてマップ可能であることが必要です。

- 引数および戻り値のJavaの算術型は、NUMBERにマップされます。

- 引数および戻り型として使用されるcharは、VARCHARにマップされます。

- 引数および戻り型として使用されるjava.lang.Stringは、VARCHARにマップされます。

- メソッドの唯一の引数がjava.lang.String型である場合は、-pubmainオプションで説明したように、特別な規則が適用されます。

- 戻り型がvoidになると、プロシージャが作成されます。

- 戻り型が算術型、charまたはjava.lang.String型の場合は、ファンクションが作成されます。

前述の規則に該当しない引数または戻り型を取るメソッドは、適格ではありません。SQL引数のOUTとIN OUT、OBJECT型およびその他多数のSQL機能に対するプロビジョニングはありません。

resolve

{-resolve | -r}

以前ロードしたクラスをloadjavaツールで強制的にコンパイルおよび解決するには、-resolveを使用します。解決はロード後に個別に行われるため、-forceを指定する必要はありません。

resolver

{-resolver | -R} resolver_specification

このオプションは、loadjavaツールが作成または置換したクラス・スキーマ・オブジェクトに明示的なリゾルバ仕様を対応付けます。

リゾルバ仕様は1つ以上の項目で構成されます。各項目の内容は、次の構文で表された名前仕様とスキーマ仕様です。

"((name_spec schema_spec) [(name_spec schema_spec)] ...)"

名前仕様は、import文における名前に類似しています。Javaの完全修飾クラス名、最終要素がワイルドカード文字のアスタリスク(*)のパッケージ名、またはアスタリスク(*)のみを指定できます。ただし、名前仕様の要素間は、ピリオド(.)ではなくスラッシュ(/)で区切る必要があります。たとえば、名前仕様a/b/*は、名前がa.bで始まるすべてのクラスに一致します。特殊な名前である*はすべてのクラス名に一致します。

スキーマ仕様として、スキーマ名またはワイルドカード文字のダッシュ(-)を指定できます。ワイルドカードは、スキーマを特定するものではなく、一致する名前への参照が解決できない場合でもクラスを無効とマークしないように解決処理に対して指示するために使用します。テスト対象のクラスで参照しているクラスをロードできない、またはロードしない場合は、ダッシュ(-)を使用します。たとえば、クラスでGUIクラスを参照していても、サーバーでの実行時はGUIがないため、このGUIクラスはコールされません。

解決処理では、名前が名前仕様に一致するスキーマ・オブジェクトが、パートナ・スキーマ仕様で指定されているスキーマで検索されます。

この解決処理では、リゾルバ仕様のリスト順にスキーマが検索されます。次に例を示します。

-resolver '((* HR) (* PUBLIC))'

これは、最初にHRで、次にPUBLICで参照を検索することを意味します。参照が解決されない場合は、参照元クラスを無効とマークし、エラー・メッセージを表示します。

次の例を考えてみます。

-resolver "((* HR) (* PUBLIC) (my/gui/* -))"

これは、最初にHRで、次にPUBLICで参照を検索することを意味します。参照先がパッケージmy.gui内のクラスで、その参照が見つからない場合は、参照元クラスを有効とマークし、エラー・メッセージは表示しません。参照先がmy.gui内のクラスでなく、その参照が見つからない場合は、参照元クラスを無効とマークし、エラー・メッセージを表示します。

user

{-user | -u} user/password[@database_url]

デフォルトでは、loadjavaツールは、-userオプションで指定されたログイン・スキーマにロードされます。別のロード先スキーマを指定するには、-schemaオプションを使用します。そのスキーマにログインする必要はありませんが、スキーマを変更するパーミッションが必要になります。

@database_urlの形式は、次に説明するように、-ociを指定するか、または-thinを指定するかによって異なります。

- -oci:@database_urlはオプションです。指定しない場合、loadjavaツールはユーザーのデフォルト・データベースを使用します。指定した場合、database_urlはTNS名またはOracle Net Servicesの名前/値リストのいずれかになります。

- -thin:@database_urlは必須です。形式はhost:lport:SIDです。
各項目は次のとおりです。

- hostは、データベースが動作しているコンピュータの名前です。

- lportは、Oracle Net Services接続のリスニング用に構成されたリスナー・ポートです。デフォルト・インストールでは5521です。

- SIDは、データベース・インスタンスの識別子です。デフォルト・インストールではORCLです。

次に、loadjavaツールのコマンド例を示します。

- デフォルトのOCIドライバでデフォルト・データベースに接続し、JAR内のファイルをTESTスキーマにロードしてから、ファイルを解決する場合

loadjava -u joe -resolve -schema TEST ServerObjects.jar
Password: password

- JDBC Thinドライバで接続し、クラス・ファイルとリソース・ファイルをロードして、各クラスを解決する場合

loadjava -thin -u HR@dbhost:5521:orcl \
-resolve alpha.class beta.props
Password: password

- alpha.classを実行できるユーザー群にBettyとBobを追加する場合

loadjava -thin -schema test -u HR@localhost:5521:orcl \
-grant BETTY,BOB alpha.class
Password: password

jarsasdbobjects

現在のloadjavaツールで処理されるJARと、それらに含まれるクラスがデータベースに格納されること、および、クラスとJARとの関連付けに関する情報がデータベースで保持されることを示します。つまり、この引数は、現在のloadjavaツールで処理されるJARが、データベース常駐JARとしてデータベースに格納されることを示します。

prependjarnames

-jarsasdbobjectsオプションと一緒に使用します。このオプションにより、異なるJARの同じ名前のクラスが同じスキーマ内で共存できます。

dropjavaツール

dropjavaツールは、loadjavaツールと逆の処理を実行します。コマンドラインでのファイル名およびJARファイルまたはZIPファイルの内容をスキーマ・オブジェクト名に変換してから、スキーマ・オブジェクトとそれに対応するダイジェスト表の行を削除します。.java、.class、.sqlj、.ser、.zip、.jarおよびリソース・ファイル名をコマンドラインに任意の順序で入力できます。

また、スキーマ・オブジェクト名を、直接dropjavaツールに指定できます。.jar、.zip、.class、.javaまたは.sqljで終わらないコマンドライン引数は、スキーマ・オブジェクト名とみなされます。複数のスキーマ・オブジェクトに該当するスキーマ・オブジェクト名を指定すると、該当するすべてのスキーマ・オブジェクトが削除されます。

クラスを削除すると、そのクラスに依存しているクラス群が無効になり、これは、上方に再帰的に連鎖します。ソースを削除すると、それから導出されたクラスが削除されます。

注意:
Javaスキーマ・オブジェクトは、最初にロードしたときと同じ方法で削除する必要があります。.sqljソース・ファイルをロードしてサーバーで変換する場合は、同じソース・ファイルでdropjavaツールを実行する必要があります。クライアントで変換してからクラスおよびリソースを直接ロードする場合は、同じクラスおよびリソースでdropjavaツールを実行します。

dropjavaツールは、コマンドラインから実行するか、またはDBMS_JAVAクラスのdropjavaメソッドを使用して実行できます。使用しているJavaアプリケーション内からdropjavaツールを実行するには、次のコマンドを使用します。

call dbms_java.dropjava('... options...');

オプションは、コマンドラインで指定する内容と同じです。各オプションは空白で区切ります。オプションをカンマで区切らないでください。ただし、-resolverオプションは例外です。接続は常にカレント・セッションに対して確立されます。したがって、-userオプションを使用して別のユーザー名を指定することはできません。

-resolverの場合は、他のすべてのオプションを最初に指定してカンマ(,)で区切り、次に-resolverオプションとその定義を指定してください。-thin、-oci、-userおよび-passwordの各オプションは、loadjavaツールのデータベース接続に関連しているため、指定しないでください。出力はstderrに送信されます。serveroutputをオンに設定し、必要に応じてdbms_java.set_outputをコールします。

この項の内容は、次のとおりです。

- 構文

- 引数の概要

- 引数の詳細

- リスト・ベースの削除

- リソースの削除

構文

dropjavaツールのコマンド構文は次のとおりです。

dropjava [options] {file.java | file.class | file.sqlj |
file.jar | file.zip | resourcefile} ...
-u | -user user/[password][@database]
[-genmissingjar JARfile]
[-jarasresource]
[-o | -oci | -oci8]
[-optionfile file]
[-optiontable table_name]
[-S | -schema schema]
[-stdout]
[-s | -synonym]
[-t | -thin]
[-v | -verbose]
[-list]
[-listfile]

引数の概要

表12-3は、dropjavaツールの引数の一覧です。

表12-3 dropjavaの引数の概要

引数

説明

-user

ユーザー名、パスワードおよびデータベース接続文字列(オプション)を指定します。ファイルはこのデータベース・インスタンスから削除されます。

filenames

.java、.class、.sqlj、.ser、.jar、.zipおよびリソース・ファイル名を、必要な数だけ組み合せて指定します。

-genmissingjar JARfile

このオプションのオペランドを処理対象のファイルとして扱います。

-jarasresource

以前にリソースとしてロードされたJARファイル全体を削除します。

-oci | -oci8

dropjavaツールに対して、OCI JDBCドライバを使用してデータベースに接続するように指示します。-ociオプションと-thinオプションは相互に排他的です。いずれも指定しない場合は、デフォルトで-ociオプションが使用されます。-ociオプションを選択すると、-user値の形式が暗黙的に使用されます。

-optionfile file

使用方法はloadjavaツールと同じです。

-optiontable table_name

使用方法はloadjavaの場合と同じです。

-schema schema

スキーマ・オブジェクトを削除するスキーマを指定します。このオプションを指定しないと、ログイン・スキーマが使用されます。他のユーザーのスキーマからスキーマ・オブジェクトを削除するには、DROP ANY PROCEDURE権限およびUPDATE ANY TABLE権限が必要です。

-stdout

stderrではなく、stdoutに出力を送信します。

-synonym

loadjavaツールを使用して作成されたPUBLICシノニムを削除します。

-thin

dropjavaツールに対して、JDBC Thinドライバを使用してデータベースと通信するように指示します。-thinオプションを選択すると、-user値の形式が暗黙的に使用されます。

-verbose

dropjavaツールに対して、実行中に詳細なステータス・メッセージを出力するように指示します。

–list

コマンドラインにリストされたクラス、Javaソースまたはリソースがクライアント・マシンまたはサーバー・マシン上に存在しない場合、これらを削除します。

-listfile

ファイルを読み取り、そのファイルにリストされたクラス、Javaソースまたはリソースがクライアント・マシンまたはサーバー・マシン上に存在しない場合はこれらを削除します。ファイルには、行ごとに完全なクラス名、Javaソース名またはリソース名の内部表現が含まれます。

引数の詳細

この項では、dropjavaツールの一部の複雑な引数について説明します。

ファイル名

dropjavaツールは、ほとんどのファイル名をloadjavaツールと同じ方法で解析します。

- .classファイル
ファイル内のクラス名を検索して、対応するスキーマ・オブジェクトを削除します。

- .javaおよび.sqljファイル
ファイル内の最初のクラス名を検索して、対応するスキーマ・オブジェクトを削除します。

- .jarおよび.zipファイル
アーカイブ・ファイル名を、コマンドラインに入力された場合と同様に処理します。

dropjavaツールは、これ以外の拡張子が付いているファイル名、または拡張子が付いていないファイル名をスキーマ・オブジェクト名として解析し、その名前に一致するすべてのソース・オブジェクト、クラス・オブジェクトおよびリソース・オブジェクトを削除します。

dropjavaツールは、スキーマ・オブジェクトに一致しないファイル名を検出すると、メッセージを表示し、残りのファイル名を処理します。

user

{-user | -u} user/password[@database]

@databaseの形式は、-ociを指定するか、または-thinを指定するかによって異なります。

- -oci:@databaseはオプションです。指定しない場合、dropjavaツールはユーザーのデフォルト・データベースを使用します。指定した場合、databaseはTNS名またはOracle Net Servicesの名前/値リストのいずれかになります。

- -thin:@databaseは必須です。形式はhost:lport:SIDです。
各項目は次のとおりです。

- hostは、データベースが動作しているコンピュータの名前です。

- lportは、Oracle Net Services接続のリスニング用に構成されたリスナー・ポートです。デフォルト・インストールでは5521です。

- SIDは、データベース・インスタンスの識別子です。デフォルト・インストールではORCLです。

次に、dropjavaツールのコマンド例を示します。

- ServerObjects.jarからロードしたデフォルト・データベース内のTESTスキーマにある、すべてのスキーマ・オブジェクトを削除する場合

dropjava -u HR -schema TEST ServerObjects.jar
Password: password

- JDBC Thinドライバで接続してから、クラス・ファイルとリソース・ファイルをユーザーのスキーマから削除する場合

dropjava -thin -u HR@dbhost:5521:orcl alpha.class beta.props
Password: password

リスト・ベースの削除

以前のバージョンのdropjavaツールでは、クライアント側またはサーバー側のユーティリティを実行するマシンにクラス、JAR、ソースおよびリソースが存在する必要がありました。現行バージョンのdropjavaには、クラスのリストに基づき、クライアント・マシンまたはサーバー・マシンに存在しない場合があるクラス、リソースまたはソースを削除できるオプションが用意されています。このリストは、コマンドライン上またはテキスト・ファイル内にある場合があります。次に例を示します。

dropjava –list –u HR –v this.is.my.class this.is.your.class
Password: password

このコマンドは、コマンドラインにリストされたクラスthis.is.my.classおよびthis.is.your.classがクライアント・マシンまたはサーバー・マシン上に存在しない場合、これらを削除します。

dropjava –listfile my.list –u HR –s –v
Password: password

このコマンドは、my.listにリストされたクラスのリストに基づき、クラス、リソースまたはソースおよびそのシノニムを削除し、冗長形式で表示します。

注意:
'-install'フラグは、変更不可のシステムが所有するスキーマ・オブジェクトのロードおよび削除を無視します。
これらのスキーマ・オブジェクトはCREATE JAVA COMMANDで指定されたランタイム・クラスおよびリソースです。

リソースの削除

サーバーに直接ロードされたリソースを削除する場合は注意が必要です。-ser2classオプションを使用せずにクライアントで変換した場合、このリソースにはプロファイルが含まれています。ソースやクラス・スキーマ・オブジェクト、またはサーバー側SQLJトランスレータで生成されたリソース・スキーマ・オブジェクトを削除する場合は、該当する.sqljソース・ファイルのパッケージ仕様に従ってスキーマ・オブジェクトが検索されます。ただし、クライアントで生成されてサーバーに直接ロードされたリソースのスキーマ・オブジェクトの完全修飾名は、.jarファイルのパス情報またはロード時にコマンドラインに指定したパス情報によって異なります。.jarファイルを使用してリソースをロードし、同じ.jarファイルを使用してリソースを削除する場合は問題ありません。ただし、コマンドラインを使用してリソースをロードする場合は、dropjavaツールを実行してリソースを削除するときに同じパス情報を指定するように注意してください。

ojvmjavaツール

ojvmjavaツールは、データベース・インスタンスのセッション・ネームスペースとの対話型インタフェースです。ojvmjavaツールを起動するときは、データベース接続引数を指定します。これによって、プロンプトが表示され、コマンドを入力できる状態になります。

シェルは実行可能プログラム、つまり、static main()メソッドを持つクラスを起動できます。起動するには、コマンドライン・インタフェースを使用するか、データベース常駐クラスをコールします。データベース常駐クラスをコールする場合、実行可能ファイルは、loadjavaツールを使用してロードしておく必要があります。

この項の内容は、次のとおりです。

- 構文

- 引数の概要

- 例

- 機能

構文

ojvmjavaツールのコマンド構文は次のとおりです。

ojvmjava {-user user[/password@database ] [options]
[@filename]
[-batch]
[-c | -command command args]
[-debug]
[-d | -database conn_string]
[-fileout filename]
[-o | -oci | -oci8]
[-oschema schema]
[-t | -thin]
[-version | -v]
-runjava [server_file_system]
-jdwp port [host]
-verbose

引数の概要

表12-4は、ojvmjavaツールの引数の一覧です。

表12-4 ojvmjavaの引数の概要

引数

説明

-user | -u

データベースに接続するためのユーザー名を指定します。この名前は大/小文字の区別がありません。名前は常に大文字に変換されます。データベース情報を指定した場合、デフォルトで使用される構文はOCIです。また、デフォルト・データベースを指定することもできます。

-password | -p

データベースに接続するためのパスワードを指定します。

@filename

実行するojvmjavaツールのコマンドを含むスクリプト・ファイルを指定します。

-batch

スクリーンに表示されたすべてのメッセージを無効にします。ヘルプ・メッセージまたはプロンプトは表示されません。入力したコマンドへの応答のみが表示されます。

-command

任意のコマンドを実行します。ojvmjavaツールをインタプリタ・モードで実行するのではなく、1つのコマンドのみ実行する場合は、このオプションの後にコマンドと引数を含む文字列を指定して実行します。指定したコマンドが実行されると、ojvmjavaツールは終了します。

-debug

デバッグ情報を表示します。

-d | -database conn_string

データベース接続文字列を指定します。

-fileout file

出力を指定のファイルにリダイレクトします。

-o | -oci | -oci8

JDBC OCIドライバを使用します。OCIドライバがデフォルトです。このフラグを使用して、@databaseまたは-databaseオプションのいずれかで使用する構文を指定します。

-o schema schema

このスキーマを使用してクラスを参照します。

-t | -thin

JDBC Thinドライバ用のデータベース構文を使用するように指定します。データベース接続文字列は、host:port:SIDの形式で指定するか、またはOracle Net Servicesの名前/値リストになります。

-verbose

接続情報を表示します。

-version

バージョンを表示します。

-runjava

Javaコマンドを実行する際にDBMS_JAVA.runjavaを使用します。引数を指定しない場合、クライアント・ファイルシステムの参照として-classpathを解析します。引数server_file_systemを指定すると、DBMS_JAVA.runjavaが通常行うように、Oracleサーバーが稼働しているファイルシステムの参照として-classpathを解析します。

-jdwp

接続が、指定のポートおよびホストでデバッガ接続をリスニングするようにします。ホストのデフォルト値はlocalhostです。

例

次に示すように、データベースorclのセッション・ネームスペース上のシェルを、ホストdbserverのリスナー・ポート2481に対してオープンします。

ojvmjava -thin -user HR@dbserver:2481:orcl
Password: password

機能

ojvmjavaツールのコマンドには様々なタイプの機能があり、次のようにグループ化されます。

- ojvmjavaツールのコマンドライン・オプション

- シェル・コマンド

ojvmjavaツールのコマンドライン・オプション

この項では、ojvmjavaツールのコマンドで使用できる次のオプションについて説明します。

- @filenameオプションでのojvmjavaツール・コマンドのスクリプト

- -runjava

- -jdwp

@filenameオプションでのojvmjavaツール・コマンドのスクリプト

この@filenameオプションは、1つ以上のojvmjavaツール・コマンドを含むスクリプト・ファイルを指定します。指定されたスクリプト・ファイルは、クライアント上に配置されます。ojvmjavaツールはファイルを読み取り、指定されたサーバー上ですべてのコマンドを実行します。さらに、スクリプト・ファイルはサーバー上で実行されるため、ファイルへの出力のリダイレクトや別のスクリプトの実行など、そのスクリプト・ファイルでのオペレーティング・システムとの対話はすべてサーバー上で行われます。別のスクリプト・ファイルを実行するようにojvmjavaツールに指示する場合、そのファイルはサーバー上の$ORACLE_HOMEに存在する必要があります。

ojvmjavaツール・コマンドの後に任意のオプションと必要な入力引数を入力する必要があります。スクリプト・ファイルには、ojvmjavaツール・コマンドおよびそれに続くオプションと入力パラメータが含まれています。入力パラメータは、コマンドラインでojvmjavaツールに渡すことができます。ojvmjavaツールは、既知のオプションをすべて処理し、その他のオプションと引数をスクリプト・ファイルに渡します。

次の例は、スクリプト・ファイルexecShellの内容を示します。

java myclass a b c

このファイルを実行するには、次のコマンドを使用します。

ojvmjava -user HR -thin -database dbserver:2481:orcl @commands
Password: password

ojvmjavaツールは既知のオプションをすべて処理し、スクリプト・ファイル内のコマンドが使用する他の入力パラメータを渡します。次の例では、パラメータは、スクリプト・ファイル内のjavaコマンドに渡されます。

スクリプト・ファイルには、ハッシュ記号(#)を使用してコメントを追加できます。コメントはojvmjavaツールでは無視されます。次に例を示します。

#this whole line is ignored by ojvmjava

-runjava

このオプションは、ojvmjavaツールのシェル・コマンドJavaがコマンドライン・インタフェースまたはデータベース常駐クラスのどちらを使用して実行可能なクラスを実行するかを制御します。-runjavaオプションが存在する場合、コマンドライン・インタフェースが使用されます。それ以外の場合、実行可能ファイルはloadjavaツールで以前にロードされたデータベース常駐クラスになります。オプションの引数server_file_systemを使用する場合、-classpath表現がOracleサーバーを実行するマシンのファイルシステム上にあることを意味します。それ以外の場合、ojvmjavaツールを実行するマシンのファイルシステム上にあるものとして解析されます。

関連項目:
「コマンドライン・インタフェースの使用」

-jdwp

このオプションは、シェル・コマンドjavaが実行可能ファイルの実行に使用される場合にリスニングするデバッガ接続を指定します。実行可能ファイルのデバッグを許可します。引数はポートおよびホストを指定します。ホストの引数のデフォルト値はlocalhostです。これらを使用して、実行可能ファイルが実行されるRDBMSセッションからDBMS_DEBUG_JDWP.CONNECT_TCPのコールを実行します。

シェル・コマンド

この項では、ojvmjavaシェル内で使用できる次のコマンドについて説明します。

- echo

- exit

- help

- java

- version

- whoami

- connect

- runjava

- jdwp

注意:
サポートされていないコマンドを入力すると、エラーがレポートされます。

表12-5に、1つ以上の共通オプションを共有するコマンドの概要を示し、共通オプションの概要を表12-5に示します。

表12-5 ojvmjavaコマンドの共通オプション

オプション

説明

-describe | -d

ツールの操作方法を要約表示します。

-help | -h

ツールの構文を要約表示します。

-version

バージョンを表示します。

echo

このコマンドは、指定された対象を正確にstdoutに表示します。これは、ほとんどの場合、スクリプト・ファイルで使用します。

構文は次のとおりです。

echo [echo_string] [args]

echo_stringは、シェル・スクリプトの起動時にスクリーンに書き込むテキストが含まれる文字列で、argsは、ユーザーが指定する入力引数です。たとえば、次のコマンドは通知を表示します。

echo "Adding an owner to the schema" &1

入力引数がHRの場合、出力は次のようになります。

Adding an owner to the schema HR

exit

このコマンドは、ojvmjavaを終了します。構文は次のとおりです。

exit

たとえば、シェルを終了するには次のコマンドを使用します。

$ exit
%

help

このコマンドは、シェル・コマンドの構文の要約を表示します。また、helpコマンドを使用すると、特定のコマンドについてオプションの要約も表示できます。構文は次のとおりです。

help [command]

java

このコマンドは、JDKのjavaコマンドに類似しています。これは、クラスのstatic main()メソッドをコールします。これを行うには、runjavaモードの設定に応じて、コマンドライン・インタフェースを使用するか、データベース常駐クラスを使用します。後者の場合、クラスはloadjavaツールを使用して以前にロードしたものである必要があります。このコマンドは、データベースで実行されるJavaコードのテストに便利です。特に、このコマンドは例外を捕捉し、クラスの標準出力と標準エラーをシェルにリダイレクトして、他のコマンド出力の場合と同様に表示します。データベース内で実行されるJavaクラスの標準出力と標準エラーの出力先は、データベース・サーバー・プロセスの1つ以上のトレース・ファイルで、これは読みにくく、また読むためにはDBA権限が必要な場合があります。

関連項目:
「コマンドライン・インタフェースの使用」

runjavaモードがオフのコマンドの構文は次のとおりです。

java [-schema schema] class [arg1 ... argn]

runjavaモードがオンのコマンドの構文は次のとおりです。

java [command-line options] class [arg1 ... argn]

コマンドライン・オプションは、表3-1で説明したいずれかのオプションになります。

表12-6は、このコマンドの引数の一覧です。

表12-6 javaの引数の概要

引数

説明

class

実行するJavaクラス・スキーマ・オブジェクトの名前を指定します。

-schema

実行するクラスを含むスキーマ名を指定します。デフォルトは実行者のスキーマです。スキーマ名は、大/小文字の区別があります。

arg1 ... argn

クラスのstatic main()メソッドに渡す引数。

次のJavaファイルWorld.javaについて考えます。

package hello;
public class World
{
public World()
{
super();
}

public static void main(String[] argv)
{
System.out.println("Hello from Oracle Database");
if (argv.length != 0)
System.out.println("You supplied " + argv.length + " arguments: ");
for (int i = 0; i < argv.length; i++)
System.out.println(" arg[" + i + "] : " + argv[i]);
}
}

次のように、クラスをコンパイル、ロード、公開および実行します。

% javac hello/World.java

% loadjava -r -user HR@localhost:2481:orcl hello/World.class
Password: password
% ojvmjava -user HR -database localhost:2481:orcl
Password: password
$ java hello.World alpha beta
Hello from Oracle Database
You supplied 2 arguments:
arg[0] : alpha
arg[1] : beta

version

このコマンドは、ojvmjavaツールのバージョンを表示します。また、指定したコマンドのバージョンも表示できます。このコマンドの構文は次のとおりです。

version [options] [command]

たとえば、次のように、シェルのバージョンを表示できます。

$ version
1.0

whoami

このコマンドは、カレント・セッションにログインしているユーザーのユーザー名を表示します。このコマンドの構文は次のとおりです。

whoami

connect

このコマンドを使用すると、クライアントで現在の接続を削除し、別の接続の説明でojvmjavaツールを再起動せずに別のデータベースに接続できます。

このコマンドの構文は次のとおりです。

connect [-service service] [-user user][-password password]

このコマンドは、次の例のように使用できます。

connect -s thin@locahost:5521:orcl -u HR/<password>
connect -s oci@locahost:5521:orcl -u HR -p <password>

表12-7は、このコマンドの引数の一覧です。

表12-7 connectの引数の概要

引数

説明

-service | -s

有効なJDBCドライバのURL(oci @<connection descriptor>およびthin@<host:port:db>)

-user | -u

接続するユーザー

-password | -p

接続に使用するパスワード

runjava

このコマンドは、runjavaモードの問合せや変更を行います。runjavaモードは、javaコマンドがコマンドライン・インタフェースを使用して実行可能ファイルを実行するかどうかを決定します。javaコマンドは次のように動作します。

- runjavaモードがオンの場合はコマンドライン・インタフェースを使用します。

- runjavaモードがオフの場合はデータベース常駐の実行可能ファイルを使用します。

関連項目:
「コマンドライン・インタフェースの使用」

引数を指定せずにrunjavaコマンドを使用すると、runjavaモードの現在の設定が表示されます。

表12-8は、このコマンドの引数の一覧です。

表12-8 runjavaの引数の概要

引数

説明

off

runjavaモードをオフにします。

on

runjavaモードをオンにします。

server_file_system

runjavaモードをオンにします。このオプションを使用する場合、-classpath表現がOracleサーバーが実行されているマシンのファイルシステム上にあることを意味します。それ以外の場合、ojvmjavaツールを実行するマシンのファイルシステム上にあるものとして解析されます。

jdwp

このコマンドは、実行可能ファイルがJavaコマンドで実行される場合にデバッガ接続がリスニングされるかどうか、およびそのリスニングの状況の問合せや変更を行います。

注意:
RDBMSセッションは、実行可能ファイルを起動する前に、指定のポートおよびホストでDBMS_DEBUG_JDWP.CONNECT_TCPコールを実行します。これはリスニングと呼ばれます。

引数を指定せずにこのコマンドを使用すると、現在の設定が表示されます。

表12-9は、このコマンドの引数の一覧です。

表12-9 jdwpの引数の概要

引数

説明

off

今後の実行可能ファイルでのリスニングを停止します。

port

リスニングを有効にして、使用するポートを指定します。

host

リスニングを有効にして、使用するホストを指定します。この引数のデフォルト値はlocalhostです。

13 データベースWebサービス

この章では、データベースWebサービスの概要、および既存のWebサービスのコール方法について説明します。この章の内容は、次のとおりです。

- データベースWebサービスの概要

- Webサービス・プロバイダとしてのOracle Databaseの使用

- Webサービス・コンシューマとしてのOracle Databaseの使用

データベースWebサービスの概要

Webサービスは、プラットフォーム、言語またはデータ形式に関係なく、Web上でのアプリケーション間の相互作用を可能にします。eXtensible Markup Language(XML)、Simple Object Access Protocol(SOAP)、Web Services Descriptiion Language(WSDL)およびUniversal Description, Discovery, and Integration(UDDI)を含む主要な構成要素は、ソフトウェア業界全体で採用されています。通常、Webサービスの対象は、中間層アプリケーション・サーバーに実装およびデプロイされたサービスです。ただし、異機種間環境および非接続環境では、データとメタデータの他に、Webサービス・インタフェースを介してストアド・プロシージャにアクセスする必要性が増大しています。

データベースWebサービス・テクノロジは、データベースを通じてWebサービスにアクセスする手法です。これには、次の2方向の動作があります。

- Webサービスとしてのデータベース・リソースへのアクセス

- データベースによる外部Webサービスの消費

Oracle Databaseは、データベース内にデプロイされているPL/SQLパッケージとJavaクラスを介して、Webサービスにアクセスできます。Oracle DatabaseのWebサービス・プロバイダへの転換によって、Javaストアド・プロシージャ、PL/SQLパッケージ、事前定義のSQL問合せおよびデータ操作言語(DML)への投資が活用されます。反対に、データベースによる外部Webサービスの消費は、SQLエンジンとの統合とともに、企業情報の統合を可能にします。

Webサービス・プロバイダとしてのOracle Databaseの使用

Webサービスでは業界標準のメカニズムを使用して、プロバイダのプラットフォームや位置、実装およびデータ形式に関係なく、リモート・コンテンツおよびリモート・アプリケーションへの容易なアクセスが提供されます。クライアント・アプリケーションでは、Oracle Databaseのデータの問合せと取得、および標準Webサービス・プロトコルを使用したストアド・プロシージャのコールが可能です。Oracle固有のデータベース接続プロトコルには依存しません。このアプローチによって、異機種間環境、分散環境、および非接続環境における高い有益性が提供されます。

データベースをサービス・プロバイダとして使用して、Webサービスからデータベースをコールできます。これによって、既存または新規のSQL、PL/SQL、Javaストアド・プロシージャまたはJavaクラスをOracle Database内で活用できます。データベース表は、Webサービス・クライアントからアクセスして操作できます。

この項の内容は、次のとおりです。

- WebサービスからのコールでのJPublisherの使用方法

- Webサービス・プロバイダとしてのOracle Databaseの機能

- WebサービスからのOracle DatabaseのコールをサポートするJPublisher

WebサービスからのコールでのJPublisherの使用方法

JPublisherを使用すると、データベース操作に対応したJavaラッパーを生成し、Oracle Application ServerのWebサービスとしてデプロイできます。

図13-1に、JPublisherを使用してPL/SQLパッケージ、SQLオブジェクト、コレクションおよびパッケージをJavaクラスとして公開する方法を示します。公開されたクラスには、WebLogic Server(WLS)Webサービス・サーブレットを介して、どのWebサービスからもアクセスできます。

図13-1 Webサービスからのデータベースのコール

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

Webサービス・プロバイダとしてのOracle Databaseの機能

Webサービス・プロバイダとしてOracle Databaseを使用する場合は、次の機能が提供されます。

- PL/SQL Webサービスの拡張
CLOB、BLOB、XMLTYPE、ref cursor、PL/SQLレコードおよび表など、さらなるPL/SQL型に対するWebサービスのサポートの拡張により、PL/SQL Webサービスが改善されます。これによって、既存のPL/SQLパッケージの大部分がWebサービスとして使用できます。

- データベース内のJavaをWebサービスとして公開
Oracle Database内にデプロイされた既存のJavaクラスをWebサービスとして公開します。データ関連のサービスを実装するJavaクラスは、中間層とデータベース間で移行できます。Javaの移植性が、結果としてデータベースの独立性につながります。

- SQL問合せWebサービスの提供
ウェアハウス問合せまたはビジネス・インテリジェンス問合せ、データ監視問合せ、およびすべての事前定義のSQL文を、Webサービスとして活用します。

- DML Webサービスの使用可能化
SQL DMLによって実装された、セキュアで、永続的なトランザクションのスケーラブルなロギング、監視および追跡の各操作をWebサービスとして提供します。DML Webサービスは、アトミックかグループ、またはバッチのINSERT操作、UPDATE操作およびDELETE操作として実装されます。

WebサービスからのOracle DatabaseのコールをサポートするJPublisher

次のJPublisherの機能は、Oracle Database内で実行されているコードへのWebサービスのコールをサポートします。

- Javaインタフェースの生成

- JPublisherスタイルとスタイル・ファイル

- REF CURSORを返して結果セットへのマッピング

- JPublisherの公開内容をフィルタするオプション

- データベース内のJavaクラスをPL/SQLのコール仕様を使用せずにコールする場合のサポート

- SQL問合せまたはDML文の公開のサポート

- 一意のメソッド名のサポート

- Oracle Streams AQのサポート

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

Webサービス・コンシューマとしてのOracle Databaseの使用

リレーショナル・データベースの格納、索引付けおよび検索の各機能を拡張すると、連携データの使用可能化に加え、半構造化データと非構造化データ(Webサービスを含む)を含めることができます。Webサービスをコールすることによって、データベースでは、株価、通貨為替相場、天気情報などのオンデマンドで生成された動的データの追跡、集計、リフレッシュおよび問合せを実行できます。

Oracle Databaseをサービス・コンシューマとして使用する例には、事前定義のデータベース・ジョブから外部Webサービスをコールして複数のサプライヤからインベントリ情報を入手し、使用しているローカルのインベントリ・データベースを更新する場合があります。他にはWebクローラの例があります。これは、データベース・ジョブをスケジュールして、多数のソースから製品情報と価格情報を照合できます。

この項の内容は、次のとおりです。

- WebサービスのコールでのOracle Databaseの使用方法

- Webサービスのデータソース(仮想表サポート)

- Webサービス・コンシューマとしてのOracle Databaseの機能

- JPublisherにおける生成の概要

- SQL型のマッピングの調整

WebサービスのコールでのOracle Databaseの使用方法

SQL、PL/SQLまたはJavaで作成されたWebサービスのクライアント・コードは、Oracle Database内で実行され、外部Webサービスをコールします。次の方法のいずれかを使用して、データベース内のJavaクライアントからWebサービスをコールできます。

- SQLおよびPL/SQLのコール仕様
Webサービスを、JPublisherで生成されたユーザー定義のファンクション・コールを使用して、SQL文またはビュー内のいずれかで直接起動するか、または変数を介して起動します。

- Pure Java staticプロキシ・クラス
JPublisherを使用して、JAX-RPC(XMLベースのリモート・プロシージャ・コールのJava API)を使用するクライアント・プロキシ・クラスを生成します。この方法では、サービスの位置がすでに認識されているため、UDDIレジストリでサービスを参照する必要がなく、Webサービスを簡単に起動できます。クライアント・プロキシ・クラスは、パラメータのマーシャリングとアンマーシャリングも含めて、SOAPリクエストの構成に必要な作業をすべて実行します。

- JAX-RPCで動的起動インタフェース(DII)を使用するPure Java
動的起動によって、クライアント・プロキシを使用することなく、SOAPリクエストを構成し、サービスにアクセスする機能が提供されます。

PL/SQLを使用してWebサービスをコールするには、UTL_DBWS PL/SQLパッケージを使用します。このパッケージでは、基本的にDIIクラスと同じApplication Program Interface(API)が使用されます。

Webサービスのデータソースを使用すると、あらゆるWebサービス・リクエストの結果を処理できます。

図13-2に、データベース内のJavaクライアントからWebサービスをコールする方法を示します。

図13-2 データベース内からのWebサービスのコール

Webサービスのデータソース(仮想表サポート)

単一または複数のWebサービスの起動から戻されるデータにアクセスするには、Webサービスのデータソースを使用して仮想表を作成します。この表を使用すると、戻された一連の行を1つの表のように問い合せることができます。

クライアントがWebサービスをコールし、その結果がデータベース内の仮想表に格納されます。結果セットはファンクション間で受け渡しできます。これによって、中間結果を保持する表を使用することなく、変換の順序を設定できます。メモリー使用量を軽減するために、1つのファンクションで一度に数行の結果セットを戻すことができます。

Webサービスでテーブル・ファンクションを使用すると、単一または複数のWebサービスからの一連の入力値を実際の表のように操作できます。次の例では、内部のSELECT文によって複数の行が作成され、それらの行の列は、WebサービスのコールCALL_WSをコールする引数として使用されます。

SELECT column1, cloumn2, ...
FROM TABLE(WS_TABFUN(CURSOR(SELECT s FROM table_name)))
WHERE ...

前述の例の場合、この表の式は、ビューなどを構成するために、他のSQL問合せで使用できます。

図13-3に、仮想表のサポートを示します。

図13-3 仮想表へのリクエスト結果の格納

Webサービス・コンシューマとしてのOracle Databaseの機能

Webサービス・コンシューマとしてOracle Databaseを使用する場合は、次の機能が提供されます。

- JavaによるWebサービスの使用
Webサービスのコール用に使いやすいインタフェースが提供されるため、開発者は下位レベルのSOAPプログラミングから解放されます。データベース内で実行中のJavaクラスは、あらかじめロードされたJavaプロキシ・クラスを使用するか、または動的起動を介して、外部Webサービスを直接コールできます。

- SQLおよびPL/SQLによるWebサービスの使用
SQL対応のツールやアプリケーションを使用すると、外部Webサービスから動的データを透過的にかつ簡単に消費できます。WebサービスのメソッドをJavaストアド・プロシージャとして公開した後は、Javaストアド・プロシージャの先頭のPL/SQLラッパーによって、すべてのJavaとSOAPのプログラミング詳細がSQLクライアントから隠されます。

- Webサービスのデータソースの使用
外部WebサービスをSQLデータソースに転換することによって、アプリケーションとデータの統合を可能にし、外部Webサービスを通常のSQL表として表示します。このテーブル・ファンクションは、外部Webサービスのコールの出力を表し、SQL問合せで使用できます。

JPublisherにおける生成の概要

JPublisherでは、WebサービスからWSDLファイルを受信して、静的Java、プロキシ・クラスまたはPL/SQLのコール仕様を作成できます。

図13-4は、Webサービスからのコール用のスタブの作成を示しています。

図13-4 Webサービスからのコール用のスタブの作成

このサポートは、次に示すJPublisherの主要なオプションを使用して作成されます。

- -proxywsdl=url
WSDL文書が指定のURLにある場合は、このオプションを使用してJAX-RPC静的クライアント・プロキシを生成します。このオプションを設定すると、インスタンス・メソッドをstaticメソッドとして公開するための追加ラッパー・クラス、およびPL/SQLラッパーが生成されます。これにより、次の手順が実行されます。

1. JAX-RPCクライアント・プロキシ・クラスを生成します。

2. ラッパー・クラスを生成し、インスタンス・メソッドをstaticメソッドとして公開します。

3. PL/SQLからアクセスする必要があるクラスのPL/SQLラッパーを生成します。

4. 生成されたコードをデータベースにロードします。

注意:
この-proxywsdlオプションは、ステップ2および3のバックグラウンドで-proxyclassesオプションを使用し、-proxyoptsの設定を入力として取得します。

コードが生成されると、データベース・クライアントは、コール仕様を使用してPL/SQLを介するか、またはJAX-RPCクライアント・プロキシ・クラスを介して、Webサービスにアクセスできます。PL/SQLラッパーはstaticメソッドを使用します。通常は、クライアントがstaticメソッドを介してWebサービスに直接アクセスすることはありません。

- -httpproxy=proxy_url
ファイアウォールを介してWSDLにアクセスする場合は、このオプションを使用して、WSDL文書のURLを解決するためのプロキシURLを指定します。

- -proxyclasses=class_list
Webサービスの場合、このオプションは-proxywsdlオプションのバックグラウンドで使用され、必要に応じて自動的に設定されます。さらに、このオプションを直接使用すると、いつでも一般的な目的で、staticメソッドを使用してJavaクラスのPL/SQLラッパーを作成し、必要に応じてラッパー・クラスを作成してインスタンス・メソッドをstaticメソッドとして公開できます。

-proxyclassesオプションは、-proxyopts設定を入力として取ります。

- -proxyopts=wrapper_specifications
このオプションでは、ラッパー・クラスおよびPL/SQLラッパー生成時のJPublisherの動作を指定します。通常、これはWebサービスに対して行われますが、必須ではありません。-proxywsdlオプションの標準的な使用方法では、-proxyoptsの設定はデフォルトのままで十分です。-proxyclassesオプションを直接使用する場合は、特別に設定した-proxyoptsを使用できます。

- -endpoint=Web_services_endpoint
このオプションは-proxywsdlオプションと併用し、Webサービス・エンドポイントを指定します。

- -sysuser=superuser_name/superuser_password
このオプションを使用して、スーパーユーザー・アカウントの名前とパスワードを指定します。これらの情報は、HTTPを使用してWebサービスにアクセスするためのパーミッションをクライアント・プロキシ・クラスに付与する際に使用します。

SQL型のマッピングの調整

現在、Oracle Application Serverでは、LOB型、XMLTYPE、REF CURSOR、OUT引数およびIN OUT引数はサポートされていませんが、PL/SQLメソッドおよびSQL型をWebサービスとして公開する代替アプローチを使用できます。

JPublisherのデフォルトのアクションを変更すると、ユーザー提供のサブクラスを使用するコードを生成できます。たとえば、REF CURSORを戻すPL/SQLメソッドがある場合、JPublisherは戻り型をjava.sql.ResultSetに自動的にマッピングします。ただし、このResultSet型はWebサービスとしては公開できません。これを解決するには、次のように、結果セットを、Webサービスがサポートする形式で戻すことができる新規のメソッドを作成します。

public String [] readRefCursorArray(String arg1, Integer arg2)
{
java.sql.ResultSet rs = getRefCursor(arg1,arg2);
...
//create a String[] from rs and return it
...
}

メソッドを作成した後、公開するメソッド自体を含むインタフェースを作成します。このマッピングは、次のコマンドを使用することで、JPublisherを使用して簡単に実行できます。

jpub -sql=MYAPP:MyAppBase:MyApp#MyAppInterf...

このコマンドの内容は次のとおりです。

- MyAppには、結果セットを戻すためのメソッドが格納されます。

- MyAppInterfは、公開するメソッドを格納するインタフェースです。

使用しているアプリケーション用にコードを変換した後は、すべてのクラス・ファイルを単一のJavaアーカイブ(JAR)ファイルにアーカイブし、Webサービス・アセンブラを使用してデプロイ可能なWebサービスのエンタープライズ・アーカイブ(EAR)ファイルを作成します。

関連項目:
『Oracle Database JPublisherユーザーズ・ガイド』

A DBMS_JAVAパッケージ

この付録では、DBMS_JAVAパッケージについて説明します。このパッケージのファンクションとプロシージャは、JavaからRDBMS機能にアクセスするためのエントリ・ポイントを提供します。

longname

FUNCTION longname (shortname VARCHAR2) RETURN VARCHAR2

指定したJavaスキーマ・オブジェクトの完全修飾名を戻します。JavaクラスとJavaメソッドには、SQL識別子の最大長を超える名前を設定できるため、Oracle JVMの内部では、SQLアクセス用の短縮名が使用されます。このファンクションは、すべての切り捨てられた名前の元のJava名を戻します。このファンクションの例では、無効なクラスの完全修飾名を次のように表示します。

SELECT dbms_java.longname (object_name) FROM user_objects
WHERE object_type = 'JAVA CLASS' AND status = 'INVALID';

関連項目:
「クラスの短縮名」

shortname

FUNCTION shortname (longname VARCHAR2) RETURN VARCHAR2

データベースにフルネームを指定するには、フルネームを入力として取得し、対応する短い名前を戻すDBMS_JAVAパッケージのshortname()ルーチンを使用できます。これは、USER_OBJECTSビューの問合せによってロードされたクラスの検証に役立ちます。

関連項目:
「クラスの短縮名」

get_compiler_option

FUNCTION get_compiler_option(name VARCHAR2, optionName VARCHAR2) RETURN VARCHAR2

optionNameパラメータで指定したオプションの値を戻します。これは、Oracle Databaseにより提供されるJavaとSQLJコンパイラに関するオプションの制御に使用するファンクションの1つです。

関連項目:
「データベース表に指定されるコンパイラ・オプション」

set_compiler_option

PROCEDURE set_compiler_option(name VARCHAR2, optionName VARCHAR2, value VARCHAR2)

Oracle Databaseにより提供されるJavaとSQLJコンパイラに関するオプションの設定に使用されます。

関連項目:
「データベース表に指定されるコンパイラ・オプション」

reset_compiler_option

PROCEDURE reset_compiler_option(name VARCHAR2, optionName VARCHAR2)

指定したコンパイラ・オプションをデフォルト値に再設定するために使用されます。

関連項目:
「データベース表に指定されるコンパイラ・オプション」

resolver

FUNCTION resolver (name VARCHAR2, owner VARCHAR2, type VARCHAR2) RETURN VARCHAR2

オブジェクトがtype型のスキーマownerのオブジェクトnameに対するリゾルバ仕様を戻します。コール元には、EXECUTE権限、およびこのファンクションを使用するように指定されたオブジェクトへのアクセス権が必要です。

nameパラメータは、このオブジェクトの短縮名です。

typeの値は、SOURCEまたはCLASSのいずれかです。

エラーがある場合は、NULLが戻されます。基礎となるオブジェクトが変更された場合は、ObjectTypeChangedExceptionがスローされます。

このファンクションは次のようにコールできます。

SELECT dbms_java.resolver('tst', 'HR', 'CLASS') FROM DUAL;

次の結果が戻されます。

DBMS_JAVA.RESOLVER('TST','HR','CLASS')
-----------------------------------------
((* HR)(* PUBLIC))

derivedFrom

FUNCTION derivedFrom (name VARCHAR2, owner VARCHAR2, type VARCHAR2) RETURN VARCHAR2

オブジェクトがtype型のスキーマownerのオブジェクトnameに対するソース名を戻します。コール元には、EXECUTE権限、およびこのファンクションを使用するように指定されたオブジェクトへのアクセス権が必要です。

nameパラメータおよび戻されたソース名は、このオブジェクトの短縮名です。

typeの値は、SOURCEまたはCLASSのいずれかです。

エラーがある場合は、NULLが戻されます。基礎となるオブジェクトが変更された場合は、ObjectTypeChangedExceptionがスローされます。

オブジェクトがOracle JVMでコンパイルされなかった場合、戻り値はNULLになります。

このファンクションは次のようにコールできます。

SELECT dbms_java.derivedFrom('tst', 'HR', 'CLASS') FROM DUAL;

次の結果が戻されます。

DBMS_JAVA.DERIVEDFROM('TST','HR','CLASS')
-----------------------------------------
tst

fixed_in_instance

FUNCTION fixed_in_instance (name VARCHAR2, owner VARCHAR2, type VARCHAR2) RETURN NUMBER

オブジェクトがtype型のスキーマownerのオブジェクトnameに対して、永続的に保持されるステータスを戻します。コール元には、EXECUTE権限、およびこのファンクションを使用するように指定されたオブジェクトへのアクセス権が必要です。

nameパラメータは、このオブジェクトの短縮名です。

typeの値は、RESOURCE、SOURCE、CLASSまたはSHARED_DATAのいずれかです。

戻される数値は、ステータスを保持しないことを示す0か、保持することを示す1のいずれかです。

このファンクションは次のようにコールできます。

SELECT dbms_java.fixed_in_instance('tst', 'HR', 'CLASS') FROM DUAL;

次の結果が戻されます。

DBMS_JAVA.FIXED_IN_INSTANCE('TST','HR','CLASS')
-----------------------------------------
0

次の文を考えてみます。

SELECT dbms_java.fixed_in_instance('java/lang/String', 'SYS', 'CLASS') FROM DUAL;

次の結果が戻されます。

DBMS_JAVA.FIXED_IN_INSTANCE('JAVA/LANG/STRING','SYS','CLASS')
-------------------------------------------------------------
1

set_output

PROCEDURE set_output (buffersize NUMBER)

Javaストアド・プロシージャの出力をリダイレクトし、DBMS_OUTPUTパッケージにトリガーします。

関連項目:
「出力のリダイレクト」

export_source

PROCEDURE export_source(name VARCHAR2, schema VARCHAR2, src BLOB)

PROCEDURE export_source(name VARCHAR2, src BLOB)

PROCEDURE export_source(name VARCHAR2, src CLOB)

PROCEDURE export_source(name varchar2, schema varchar2, src CLOB)

Javaソースを、Javaソース・スキーマ・オブジェクトとしてOracle Databaseにエクスポートするために使用されます。ソースは、nameパラメータを使用して指定します。このソースは、BLOBオブジェクトまたはCLOBオブジェクトにエクスポートできます。ソースの内部表現にはUTF8形式が使用されるため、BLOBへのソースの格納にもこの形式が使用されます。ソース・スキーマ・オブジェクトは指定のスキーマで作成されます。スキーマが未指定の場合は、現行スキーマが使用されます。

export_class

PROCEDURE export_class(name VARCHAR2, schema VARCHAR2, src BLOB)

PROCEDURE export_class(name VARCHAR2, src BLOB)

nameパラメータで指定したJavaクラスを、Javaクラス・スキーマ・オブジェクトとしてOracle Databaseにエクスポートするために使用されます。クラスのエクスポート先はBLOBオブジェクトのみで、CLOBオブジェクトにはエクスポートできません。スキーマが指定されている場合、クラス・スキーマ・オブジェクトは、現行スキーマの他に、指定されたスキーマにも作成されます。

export_resource

PROCEDURE export_resource(name VARCHAR2, schema VARCHAR2, src BLOB)

PROCEDURE export_resource(name VARCHAR2, src BLOB)

PROCEDURE export_resource(name VARCHAR2, schema VARCHAR2, src CLOB)

PROCEDURE export_resource(name VARCHAR2, src CLOB)

nameパラメータで指定したリソースが、schemaパラメータで指定したスキーマのリソース・スキーマ・オブジェクトとしてOracle Databaseにエクスポートされます。スキーマが未指定の場合は、現行スキーマが使用されます。このリソースは、CLOBオブジェクトまたはBLOBオブジェクトのいずれにもエクスポートできます。

loadjava

PROCEDURE loadjava(options VARCHAR2)
PROCEDURE loadjava(options VARCHAR2, resolver VARCHAR2)
PROCEDURE loadjava(options VARCHAR2, resolver VARCHAR2, status NUMBER)

loadjavaコマンドライン・ツールではなく、コールを使用して、データベースに複数のクラスをロードできます。このプロシージャは、次のように、使用しているJavaアプリケーション内でコールできます。

CALL dbms_java.loadjava('... options...');

オプションは、コマンドラインで指定する内容と同じです。各オプションは、スペースで区切る必要があります。オプションをカンマで区切らないでください。これに関する唯一の例外は、スペースを含むloadjava -resolverオプションです。-resolverの場合は、次のように、最初にすべての他のオプションを指定してカンマで区切り、次に-resolverオプションを指定します。

CALL dbms_java.loadjava('... options...', 'resolver_options');

-thin、-oci、-userおよび-passwordの各オプションはデータベース接続に関連しているため、指定しないでください。出力は、System.errに送られます。通常、出力はトレース・ファイルに保存されますが、リダイレクトできます。

関連項目:
「loadjavaツール」

dropjava

PROCEDURE dropjava(options VARCHAR2)

dropjavaコマンドライン・ツールではなく、コールを使用して、データベース内のクラスを削除できます。このプロシージャは、次のように、使用しているJavaアプリケーション内でコールできます。

CALL dbms_java.dropjava('... options...');

関連項目:
「dropjavaツール」

grant_permission

PROCEDURE grant_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2,
permission_action VARCHAR2)

grant_permissionがコールされると、ポリシー表のアクティブな行によって、permission_type、permission_nameおよびpermission_actionで指定されている許可がgranteeに付与されます。これらのパラメータと一致する有効な行がすでに存在する場合、表は変更されません。行は存在するが無効になっている場合、有効化されます。一致する行が存在しない場合、1行が挿入されます。パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前です。

- permission_actionは許可のアクションです。

関連項目:
「各パーミッションのファイングレイン定義」

grant_permission

PROCEDURE grant_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2,
permission_action VARCHAR2, key OUT NUMBER)

パラメータで指定されている許可を付与する新しい行が、ポリシー表に追加されます。

パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前です。

- permission_actionは許可のアクションです。

- keyは、許可を付与する、新しく挿入される行のキーです。エラーが発生した場合、この値は-1です。

関連項目:
「各パーミッションのファイングレイン定義」

restrict_permission

PROCEDURE restrict_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2,
permission_action VARCHAR2)

ポリシー表のアクティブな行によって、permission_type、permission_nameおよびpermission_actionで指定されている許可がgranteeに制限されます。これらのパラメータと一致する、制限している行がすでに存在する場合、表は変更されません。一致する行が存在しない場合、1行が挿入されます。

パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前です。

- permission_actionは許可のアクションです。

関連項目:
「各パーミッションのファイングレイン定義」

restrict_permission

PROCEDURE restrict_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2,
permission_action VARCHAR2, key OUT NUMBER)

パラメータで指定されている許可を制限する新しい行が、ポリシー表に追加されます。

パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前です。

- permission_actionは許可のアクションです。

- keyは、許可を付与する、新しく挿入される行のキーです。エラーが発生した場合、この値は-1です。

関連項目:
「各パーミッションのファイングレイン定義」

grant_policy_permission

PROCEDURE grant_policy_permission(grantee VARCHAR2, permission_schema VARCHAR2, permission_type VARCHAR2,
permission_name VARCHAR2)

PolicyTablePermission許可を付与するためのgrant_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2, permission_action VARCHAR2)プロシージャの特殊なバージョンです。

パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_schemaは許可のスキーマです。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前であり、グロブ・アスタリスク('*')にできます。

関連項目:
「ポリシー表を更新するための管理パーミッションの取得」

grant_policy_permission

PROCEDURE grant_policy_permission(grantee VARCHAR2, permission_schema VARCHAR2, permission_type VARCHAR2,
permission_name VARCHAR2, key OUT NUMBER)

PolicyTablePermission許可を付与するためのgrant_permission(grantee VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2, permission_action VARCHAR2, key OUT NUMBER)プロシージャの特殊なバージョンです。パラメータの説明

- granteeはスキーマまたはロールの名前です。

- permission_schemaは許可のスキーマです。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前であり、グロブ・アスタリスク('*')にできます。

- keyは、許可を付与する、新しく挿入される行のキーです。エラーが発生した場合、この値は-1です。

関連項目:
「ポリシー表を更新するための管理パーミッションの取得」

revoke_permission

PROCEDURE revoke_permission(permission_schema VARCHAR2, permission_type VARCHAR2, permission_name VARCHAR2,
permission_action VARCHAR2)

ポリシー表の、パラメータと一致するアクティブな許可をすべて無効にします。結果は、行が一致するたびに"disable_permission"プロシージャをコールした場合と同じになります。行は削除されずに表に残り、revoke_permissionプロシージャのパラメータと一致するパラメータを使用して"grant_permission"プロシージャをコールすることによってアクティブにできます。

パラメータの説明

- permission_schemaは、スキーマまたはロールの名前です。

- permission_typeは、java.lang.security.Permissionを拡張するクラスの完全修飾名です。

- permission_nameは許可の名前です。

- permission_actionは許可のアクションです。

関連項目:
「パーミッションの使用可能または使用禁止」

disable_permission

PROCEDURE disable_permission(key NUMBER)

指定したキーと一致する既存のポリシー表行を無効にします。行はINACTIVE行として表に残ります。キーが行を指定していない場合、エラーは報告されません。disable_permissionプロシージャは、ポリシー表にアクセスするためのユーザー許可を確認し、場合によってSecurityExceptionをスローします。

関連項目:
「パーミッションの使用可能または使用禁止」

enable_permission

PROCEDURE enable_permission(key NUMBER)

指定したキーと一致する既存のポリシー表行を有効にします。キーが行を指定していない場合、エラーは報告されません。enable_permissionプロシージャは、ポリシー表にアクセスするためのユーザー許可を確認し、場合によってSecurityExceptionをスローします。

関連項目:
「パーミッションの使用可能または使用禁止」

delete_permission

PROCEDURE delete_permission(key NUMBER)

指定したキーと一致する既存のポリシー表行を削除します。行を削除する前に、"disable_permission"で示されているように行を無効にする必要があります。delete_permissionプロシージャは、行がまだアクティブになっている場合や、keyと一致する行がない場合は機能しません。

関連項目:
「パーミッションの使用可能または使用禁止」

set_preference

PROCEDURE set_preference(user VARCHAR2, type VARCHAR2, abspath VARCHAR2, key VARCHAR2, value VARCHAR2)

次のようにして、SYS:java$prefs$表に行を挿入または更新します。

CALL dbms_java.set_preference('HR', 'U', '/my/package/method/three', 'windowsize', '22:32');

userパラメータには、設定項目の連結先スキーマの名前を指定します。ログイン・スキーマがSYSではない場合、userには、現在のログイン・スキーマを指定する必要があり、指定しないと、INSERTに失敗します。typeパラメータには、ユーザー設定項目を示す値Uを指定するか、またはシステム設定項目を示すSを指定できます。abspathパラメータには、設定項目の絶対パスを指定します。keyは参照に使用する設定項目キー、valueは設定項目キーの値です。

runjava

FUNCTION runjava(cmdline VARCHAR2) RETURN VARCHAR2

Javaコマンドラインを唯一の引数として受け入れ、Oracle JVMでこれを実行します。

関連項目:
「コマンドライン・インタフェースの使用」

runjava_in_current_session

FUNCTION runjava_in_current_session(cmdline VARCHAR2) RETURN VARCHAR2

現在のコマンドラインを実行する前に、以前にJavaを使用したときからセッションに残っているJavaの状態を消去しない点を除き、runjavaファンクションと同じです。

関連項目:
「コマンドライン・インタフェースの使用」

set_property

FUNCTION set_property(name VARCHAR2, value VARCHAR2) RETURN VARCHAR2

Javaセッションが初期化されると、RDBMSの現行セッションの期間に使用されるシステム・プロパティの値を設定します。

注意:
SET_PROPERTYファンクションを実行するには、ユーザーはプロパティ名のSYS:java.util.PropertyPermissionに対する書込みパーミッションを保持する必要があります。このパーミッションを付与するには、次のコマンドを使用します。

call dbms_java.grant_permission( '<user_name>', 'SYS:java.util.PropertyPermission', '<property_name>', 'write' );

関連項目:
「システム・プロパティの設定」

get_property

FUNCTION get_property(name VARCHAR2) RETURN VARCHAR2

set_propertyで以前に設定された値を戻します。

関連項目:
「システム・プロパティの設定」

remove_property

FUNCTION remove_property(name VARCHAR2) RETURN VARCHAR2

set_propertyで以前に設定された値を削除します。

注意:
remove_propertyファンクションを実行するには、ユーザーはプロパティ名のSYS:java.util.PropertyPermissionに対する書込みパーミッションを保持する必要があります。このパーミッションを付与するには、次のコマンドを使用します。

call dbms_java.grant_permission( '<user_name>', 'SYS:java.util.PropertyPermission', '<property_name>', 'write' );

関連項目:
「システム・プロパティの設定」

show_property

FUNCTION show_property(name VARCHAR2) RETURN VARCHAR2

nameがNULLの場合、入力名または設定されたすべてのプロパティのバインディングについて、name = valueという形式のメッセージを表示します。

関連項目:
「システム・プロパティの設定」

set_output_to_sql

FUNCTION set_output_to_sql (id VARCHAR2,
stmt VARCHAR2,
bindings VARCHAR2,
no_newline_stmt VARCHAR2 default null,
no_newline_bindings VARCHAR2 default null,
newline_only_stmt VARCHAR2 default null,
newline_only_bindings VARCHAR2 default null,
maximum_line_segment_length NUMBER default 0,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1,
include_newlines NUMBER default 0,
eager NUMBER default 0) RETURN VARCHAR2

デフォルトのSystem.outおよびSystem.errへの出力ストリームが発生すると、SQL文の実行命令で構成される指定の出力仕様を定義します。

SQL文の引数の有効なコマンドは、次のいずれかのキーワード(大/小文字が区別されます)から始まり、その後に空白またはタブが続きます。

- SELECT

- INSERT

- DELETE

- UPDATE

- CALL

関連項目:
「サーバー上の出力のリダイレクト」

remove_output_to_sql

FUNCTION remove_output_to_sql (id VARCHAR2) RETURN VARCHAR2

set_output_to_sqlで作成された仕様を削除します。

関連項目:
「サーバー上の出力のリダイレクト」

enable_output_to_sql

FUNCTION enable_output_to_sql (id VARCHAR2) RETURN VARCHAR2

set_output_to_sqlで作成された後、disable_output_to_sqlで無効化された仕様を再度有効にします。

関連項目:
「サーバー上の出力のリダイレクト」

disable_output_to_sql

FUNCTION disable_output_to_sql (id VARCHAR2) RETURN VARCHAR2

set_output_to_sqlで作成された仕様を無効にします。

関連項目:
「サーバー上の出力のリダイレクト」

query_output_to_sql

FUNCTION query_output_to_sql (id VARCHAR2) RETURN VARCHAR2

set_output_to_sqlで作成された仕様を説明するメッセージを戻します。

関連項目:
「サーバー上の出力のリダイレクト」

set_output_to_java

FUNCTION set_output_to_java (id VARCHAR2,
class_name VARCHAR2,
class_schema VARCHAR2,
method VARCHAR2,
bindings VARCHAR2,
no_newline_method VARCHAR2 default null,
no_newline_bindings VARCHAR2 default null,
newline_only_method VARCHAR2 default null,
newline_only_bindings VARCHAR2 default null,
maximum_line_segment_length NUMBER default 0,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1,
include_newlines NUMBER default 0,
eager NUMBER default 0,
initialization_statement VARCHAR2 default null,
finalization_statement VARCHAR2 default null)RETURN VARCHAR2

デフォルトのSystem.outおよびSystem.errへの出力ストリームが発生すると、Javaメソッドの実行命令で構成される指定の出力仕様を定義します。

SQL文の引数の有効なコマンドは、次のいずれかのキーワード(大/小文字が区別されます)から始まり、その後に空白またはタブが続きます。

- SELECT

- INSERT

- DELETE

- UPDATE

- CALL

関連項目:
「サーバー上の出力のリダイレクト」

remove_output_to_java

FUNCTION remove_output_to_java (id VARCHAR2) RETURN VARCHAR2

set_output_to_javaで作成された仕様を削除します。

関連項目:
「サーバー上の出力のリダイレクト」

enable_output_to_java

FUNCTION enable_output_to_java (id VARCHAR2) RETURN VARCHAR2

set_output_to_javaで作成された後、disable_output_to_javaで無効化された仕様を再度有効にします。

関連項目:
「サーバー上の出力のリダイレクト」

disable_output_to_java

FUNCTION disable_output_to_java (id VARCHAR2) RETURN VARCHAR2

set_output_to_javaで作成された仕様を無効にします。

関連項目:
「サーバー上の出力のリダイレクト」

query_output_to_java

FUNCTION query_output_to_java (id VARCHAR2) RETURN VARCHAR2

set_output_to_javaで作成された仕様を説明するメッセージを戻します。

関連項目:
「サーバー上の出力のリダイレクト」

set_output_to_file

FUNCTION set_output_to_file (id VARCHAR2,
file_path VARCHAR2,
allow_replace NUMBER default 1,
from_stdout NUMBER default 1,
from_stderr NUMBER default 1) RETURN VARCHAR2

デフォルトのSystem.outに送信された出力を捕捉し、出力を捕捉する命令を構成する指定の出力仕様を定義します。

System.errストリームで、その出力を特定のファイルに追加します。

関連項目:
「サーバー上の出力のリダイレクト」

remove_output_to_file

FUNCTION remove_output_to_file (id VARCHAR2) RETURN VARCHAR2

set_output_to_fileで作成された仕様を削除します。

関連項目:
「サーバー上の出力のリダイレクト」

enable_output_to_file

FUNCTION enable_output_to_file (id VARCHAR2) RETURN VARCHAR2

set_output_to_fileで作成された後、disable_output_to_fileで無効化された仕様を再度有効にします。

関連項目:
「サーバー上の出力のリダイレクト」

disable_output_to_file

FUNCTION disable_output_to_file (id VARCHAR2) RETURN VARCHAR2

set_output_to_fileで作成された仕様を無効にします。

関連項目:
「サーバー上の出力のリダイレクト」

query_output_to_file

FUNCTION query_output_to_file (id VARCHAR2) RETURN VARCHAR2

set_output_to_fileで作成された仕様を説明するメッセージを戻します。

関連項目:
「サーバー上の出力のリダイレクト」

enable_output_to_trc

PROCEDURE enable_output_to_trc

disable_output_to_trcプロシージャで無効化された.trcファイルへのSystem.outおよびSystem.errの出力を再び有効にします。

関連項目:
「サーバー上の出力のリダイレクト」

disable_output_to_trc

PROCEDURE disable_output_to_trc

System.outおよびSystem.errの出力が.trcファイルに表示されないようにします。

関連項目:
「サーバー上の出力のリダイレクト」

query_output_to_trc

FUNCTION query_output_to_trc RETURN VARCHAR2

System.outおよびSystem.errの.trcファイルへの出力が現在有効になっているかどうかを表示する値を戻します。

関連項目:
「サーバー上の出力のリダイレクト」

endsession

FUNCTION endsession RETURN VARCHAR2

以前にJavaを実行したときからRDBMS現行セッションに残っているJavaセッションの状態をすべて消去します。

関連項目:
「Javaセッションの状態に使用する2層の期間」

endsession_and_related_state

FUNCTION endsession_and_related_state RETURN VARCHAR2

以前にJavaを実行したときからRDBMS現行セッションに残っているJavaセッションの状態と、Javaの実行に関連するサポート・データをすべて消去します。

関連項目:
「Javaセッションの状態に使用する2層の期間」

set_native_compiler_option

PROCEDURE set_native_compiler_option(optionName VARCHAR2,
value VARCHAR2)

ネイティブ・コンパイラのオプションを現行スキーマの指定の値に設定します。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

unset_native_compiler_option

PROCEDURE unset_native_compiler_option(optionName VARCHAR2,
value VARCHAR2)

現行スキーマについて、ネイティブ・コンパイラのオプション/値のペアの設定を解除します。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

compile_class

FUNCTION compile_class(classname VARCHAR2) RETURN NUMBER

現行スキーマのclassnameで特定されるクラスで定義されたすべてのメソッドをコンパイルします。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

uncompile_class

FUNCTION uncompile_class(classname VARCHAR2,
permanentp NUMBER default 0) RETURN NUMBER

現行スキーマのclassnameで特定されるクラスで定義されたすべてのメソッドをアンコンパイルします。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

compile_method

FUNCTION compile_method(classname  VARCHAR2,
methodname VARCHAR2,
methodsig  VARCHAR2) RETURN NUMBER

現行スキーマのclassnameで特定されるクラスで定義されたnameおよびJava typeシグネチャで指定したメソッドをコンパイルします。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

uncompile_method

FUNCTION uncompile_method(classname  VARCHAR2,
methodname VARCHAR2,
methodsig  VARCHAR2,
permanentp NUMBER default 0) RETURN NUMBER

現行スキーマのclassnameで特定されるクラスで定義されたnameおよびJava typeシグネチャで指定したメソッドをアンコンパイルします。

関連項目:
「Oracle JVMのJust-In-Time(JIT)コンパイラ」

start_jmx_agent

PROCEDURE start_jmx_agent(port VARCHAR2 default NULL,
ssl  VARCHAR2 default NULL,
auth VARCHAR2 default NULL)

特定のセッションでJMXエージェントを起動します。通常、エージェントはセッションの期間内はアクティブのままです。

関連項目:
「JMXを使用したアプリケーションの管理」

set_runtime_exec_credentials

PROCEDURE set_runtime_exec_credentials(dbuser VARCHAR2,
osuser VARCHAR2,
ospass VARCHAR2)

dbuserはデータベース・ユーザー名またはスキーマ名で、osuser、ospassはOSアカウント資格証明です。

データベース・ユーザー/スキーマdbuserを、オペレーティング・システム(OS)資格証明のペアosuser/ospassと関連付けます。この関連付けは暗号化されて、SYSユーザーが所有する表に格納されます。新しい有効な関連付けが確立された後は、java.lang.Runtime.execメソッドによって分岐された新しいOSプロセスや、dbuserがOSコマンドを実行するために起動されたProceessBuilderはいずれも、OracleプロセスのOS IDとしてでなくUID osuserとして実行されます。つまり、分岐したプロセスのUIDビットはUID osuserに設定されます。

注意:
DBAおよびセキュリティ管理者は、このプロシージャを使用して、Oracle DatabaseにデプロイされたJavaアプリケーションのセキュリティを強化します。DBAは、より権限の小さいアカウントを指定することによって、生成されるプロセスの権限およびアクセス権を適宜制限できます。set_runtime_exec_credentialsプロシージャを使用するには、SYSユーザーである必要があり、そうでない場合は「ORA-01031: 権限が不足しています」エラーが発生します。無効なアカウント資格証明を使用すると、新しいプロセスの作成時にIOExceptionが発生します。

このプロシージャの使用方法の例を次に示します。

例1

次のコマンドは、ユーザー/スキーマDBUSERを資格証明osuser/ospassにバインドします。

dbms_java.set_runtime_exec_credentials('DBUSER', 'osuser', 'ospass');

例2

次のいずれかのコマンドは、DBUSERと資格証明osuser/ospassの関連付けをアンバインドします。

dbms_java.set_runtime_exec_credentials('DBUSER', '', '');

dbms_java.set_runtime_exec_credentials('DBUSER', null, null);

注意:
set_runtime_exec_credentialsプロシージャを使用するには、Oracleのjssu機能を構成して、Oracle製品のインストール時にUID rootを設定する必要があり、そうしない場合はプロセスの作成時にprocess spawn via jssu failed...というIOExceptionが発生する可能性があります。

関連項目:
「Oracle DatabaseでのRuntime.exec機能のセキュアな使用」

B クラスパスの拡張機能およびユーザー・クラスロード・メタデータ

この項では、-classpath検索パスの拡張機能とユーザー・クラスロード・メタデータについて説明します。

クラスパスの拡張機能

この項では、コマンドライン・インタフェースで使用する検索パスでデータベース常駐オブジェクトとバイト・セットの仕様を許可する、-classpath検索パスおよびjserver URLプロトコル構文の拡張機能について説明します。

jserverQuotedClassPathTermPrefix

クラスパス表現が文字列jserverQuotedClassPathTermPrefixで始まる場合、クラスパス表現に含まれるFile.pathSeparator文字に関係なく、この文字列が次に出現することによってクラスパス表現が拡張されます。この文字列の実際の値は、システム・プロパティjserver.quoted.classpath.term.prefixによって指定されます。プロパティが定義されない場合、デフォルト値は||です。

jserverURLPrefix

引用符の付かないクラスパス表現が文字列jserverURLPrefixで始まる場合、その表現の残りの部分はURLとして扱われます。この文字列の値は、システム・プロパティjserver.url.in.classpath.prefixによって指定されます。この値がnullの場合、先頭が次の3つの接頭辞のいずれでもない引用符の付いた表現は、URLとして扱われます。

- jserverSpecialTokenPrefix(値が設定される場合)

- JSERVER_CP

- JSERVER_SCHEMAc

注意:
引用符の付いた表現とは、jserverQuotedClassPathTermPrefixの値である文字列で開始および終了する表現です。引用符の付かない表現とは、引用符で囲まれていない場合は元の表現全体、または先頭と末尾のjserverQuotedClassPathTermPrefixで囲まれている、引用符の付いた表現の一部になります。

jserverSpecialTokenPrefix

文字列jserverSpecialTokenPrefixの値は、システム・プロパティjserver.specialtoken.in.classpath.prefixによって指定されます。この値がnullではない場合、この文字列が先頭にある場合のみ、接頭辞JSERVER_CPおよびJSERVER_SCHEMAcが認識されます。

関連項目:
「JSERVER_CP」および「JSERVER_SCHEMAc」

JSERVER_CP

リテラルな部分文字列JSERVER_CPで始まるクラスパス表現は、JSERVER_CPがjserver:/CPに置き換えられてURLに変換されます。

JSERVER_SCHEMAc

リテラルな部分文字列JSERVER_SCHEMAcで始まるクラスパス表現は、JSERVER_SCHEMAcがjserver:/CPcSCHEMAcに置き換えられてURLに変換されます。cは任意の文字ですが、通常は/になります。つまり、JSERVER_SCHEMAc + <remaining string>という形式の表現は、<remaining string>で特定されるスキーマで共有システム・クラスロードのクラスおよびリソースを検索するための規定として扱われます。たとえば、JSERVER_SCHEMA/HRという表現はjserver:/CP/SCHEMA/HRと同じであり、HRという名前のスキーマで共有クラスおよびリソースを検索するよう指示します。

jserver:/CPの一般的な構文

jserver:/CPで始まるURLは、クラスパス表現としてのみ意味があります。jserver:/CPの後に続く最初の文字は、文字列の残りの部分のトークン・セパレータとして使用されます。これは、通常は/になります。後に続くトークンは次のようになります。

- 最初のトークンとして考えられる値は、JAR、RESOURCEまたはSHARED_DATAで、RESOURCEはJavaリソース・オブジェクト、SHARED_DATAはJava共有データ・オブジェクト、JARはデータベース常駐のJARオブジェクトを示します。このトークンはオプションで、すべての値の大文字と小文字は区別されません。これらのいずれかが存在する場合、そのURLはJAR指定子と呼ばれます。それ以外の場合は、SCHEMA指定子と呼ばれます。

- 2番目のトークンの値はPRIVATEです。これはオプションのトークンで、大文字と小文字は区別されません。

- 3番目のトークンの値はSCHEMAです。これは必須のトークンで、大文字と小文字は区別されません。

- 4番目のトークンは必須です。スキーマ名として解析されます。

- 5番目のトークンは、JAR指定子の場合は必須、SCHEMA指定子の場合は禁止されています。存在する場合は、4番目のトークンで特定されるスキーマのオブジェクト名として解析されます。

機能面では、クラスパス表現は、検索対象のクラスまたはリソース名と一致するオブジェクトの検索に使用します。SCHEMA指定子の場合、オブジェクトは指定のスキーマで検索されます。JAR指定子の場合、スキーマ内の特定のオブジェクトがURLの5番目のトークンで特定されます。このオブジェクトはJARとして扱われ、検索対象オブジェクトがJAR内で名前に基づいて検索されます。データベース常駐のJAR内でクラスを検索する場合、スキーマでクラスをクラス・オブジェクトとして検索することを意味します。それ以外は、JARオブジェクトの実際のバイトで検索オブジェクトを検索することを意味します。

検索対象オブジェクトは、次の条件を満たす場合、データベースのJavaクラス・オブジェクトになります。

- 検索名が.classで終わる場合

- URLがデータベース常駐JARのSCHEMA指定子またはJAR指定子のいずれかである場合

このようなクラス・オブジェクトは次のようになります。

- 共有システム・クラスロードのクラスとしてロードされます。これは、オプションの2番目のトークンであるPRIVATEがない場合に実行されます。

- バイトコードのセットとして解析され、プライベート・ユーザー・クラスロードのクラスとしてdefineClassメソッドでロードされます。これは、オプションの2番目のトークンであるPRIVATEが存在する場合に実行されます。

注意:
クラスパス表現からロードされたクラスがjserver URLマーカーで始まらない場合、常にプライベートのユーザー・クラスロードのクラスになります。

ユーザー・クラスロード・メタデータ

11gリリース1 (11.1)以降には、データベースの作成やアップグレード時に次の方法で作成される新しいシステム表がjavavm/install/initjvma.sqlにあります。

create table java$jvm$runtime$parameters (owner# number not null,flags number);
create unique index java$jvm$runtime$parameters$i on java$jvm$runtime$parameters(owner#);

この表は、javavm/install/rmjvm.sqlでダウングレード中に削除されます。プライベート・クラス・メタデータを共有してDBA権限を保持する場合は、この表を手動で移入できます。規則では、所有者IDと一致する行がある場合、この行のフラグ値は、owner# = -1(ある場合)の行のフラグ値によってビット単位で論理積(AND)演算されます。このような一致する行が存在しない場合、結果のビット・セットは-1(すべてのビット・セット)になります。ビット0(1<<0)が結果で設定されると、セッションは既存の共有プライベート・メタデータを共有しようとします。ビット1(1<<1)が結果で設定されると、セッションは既存の共有メタデータが検出されない場合に共有メタデータを作成します。デフォルトでは、表に行はありません。そのため、すべてのセッションで共有プライベート・メタデータを使用して作成します。

索引
A B C D E F G H I J K L M N O P R S T U V W

A

actメソッド, 2.12.2, 2.12.2

アプリケーション

コンパイル, 2.4.1

開発, 8

開発, 2.1

セッションでの実行, 2.1

実行制御, 2.2

実行権限, 2.4.5

起動, 3.1

サーバー上で実行, 3.2

スレッド, 2.11

属性, 5.1.3, 6.5

宣言, 6.5.1

認証, 10.1

メカニズム, 10.3

AUTHID句, 6.3, 6.4, 6.5

B

BasicPermission, 10.2.2.1

本体

パッケージ, 6.4

SQLオブジェクト型, 6.5

バイトコード

定義済, 1.1.3

定義, 1.5.2

検証, 2.4.2

検証機能, 2.4.2

C

コール

定義, 1.3

複数コールでのリソース管理, 2.12.7

静的フィールド, 2.1

コール・メモリー, 2.1 コール仕様, 3.1.1

定義, 6.2

データ型のマッピング, 6.2.2

オブジェクト型, 6.5

パッケージ化, 6.4

トップレベル, 6.3

概要, 6.1

Callbackクラス

actメソッド, 2.12.2

クラス

ローダー, 1.5.4

クラス

監査, 2.4.9

定義, 1.1.1.1

動的ロード, 1.2.6

実行, 2.2

フィールド, 1.1.1.1

階層, 1.1.4

継承, 1.1.4

解析, 2.2

ロード, 2.2, 2.4.4

ロード・パーミッション, 10.2.4

有効とマーク, 2.4.2

メソッド, 1.1.1.1

名前, 2.6

公開, 2.4.8, 6

依存関係の解決, 2.4.2

参照の解決, 2.4.2

スキーマ・オブジェクト, 2.3, 2.4.2, 2.4.4, 2.4.4

短縮名, 2.6

単一の継承, 1.1.1.4

.classファイル, 2.3, 2.4.4, 2.4.4 クラス・インタフェース

forNameメソッド, 2.7

クラス・スキーマ・オブジェクト, 2.4.4, 2.4.4, 12.1, 12.3 ClassForName

lookupClassメソッド, 2.7, 2.7.3

classForNameAndSchemaメソッド, 2.7.2 ClassNotFoundException, 2.7 CLASSPATH, 2.3, 2.7 クライアント

JDKのインストール, 4.4.1

環境変数の設定, 4.4.2

設定, 4.4.1

CodeSourceクラス, 10.2.1

equalsメソッド, 10.2.1

impliesメソッド, 10.2.1

コンパイル, 1.5.2, 2.4

エラー・メッセージ, 2.4.1.2, 12.4

オプション, 2.4.1.4, 12.4

ランタイム, 2.4.1, 2.4.1.3

構成, 4

JVM, 4.2

パフォーマンス, 9.2

接続

セキュリティ, 10.1

コンストラクタ・メソッド, 6.5.2.2 コンテキスト

ランタイム, 5.1

ストアド・プロシージャ, 5.1

CREATE JAVA文, 5.3, 5.3

D

データの機密保護, 10.1

データ型

マッピング, 6.2.2

データベース

権限, 10.2

スキーマ計画, 8.1

トリガー, 7.2

トリガー, 5.1.2

データベース・トリガー

Javaのコール, 7.2

DBA_JAVA_POLICYビュー, 10.2.2, 10.2.2.1, 10.2.2.1 DBMS_JAVAパッケージ, 4.3, 7.1.1

compile_class, A.54

compile_method, A.56, A.56

delete_permissionメソッド, 10.2.2.1, A.24

derivedFromメソッド, A.7

disable_output_to_file, A.45

disable_output_to_java, A.40

disable_output_to_sql, A.35

disable_output_to_trc, A.48

disable_permissionメソッド, 10.2.2.1, A.22

dropjavaメソッド, A.14

enable_output_to_file, A.44

enable_output_to_java, A.39

enable_output_to_sql, A.34

enable_output_to_trc, A.47

enable_permissionメソッド, 10.2.2.1, A.23

endsession, A.50

endsession_and_related_state, A.51

export_classメソッド, A.11

export_resourceメソッド, A.12

export_sourceメソッド, A.10

fixed_in_instanceメソッド, A.8

get property, A.29

get_compiler_optionメソッド, A.3

grant_permissionメソッド, 10.2.2.1, A.15, A.16

grant_policy_permissionメソッド, 10.2.2.1, 10.2.2.1, 10.2.2.1, A.19, A.20

loadjavaメソッド, A.13

longnameメソッド, 2.4.7, 2.6, A.1

パーミッションの変更, 10.2.2.1

PolicyTableパーミッションの変更, 10.2.2.1, 10.2.2.1

query_output_to_file, A.46

query_output_to_sql, A.36

query_output_to_trc, A.49

remove property, A.30

remove_output_to_file, A.43

remove_output_to_java, A.38

remove_output_to_sql, A.33

reset_compiler_optionメソッド, A.5

resolverメソッド, A.6

restrict_permissionメソッド, 10.2.2.1, A.17, A.18

revoke_permissionメソッド, 10.2.2.1, A.21

runjava, A.26

runjava_in_current_session, A.27

set property, A.28

set_compiler_optionメソッド, A.4

set_native_compiler_option, A.52

set_outputメソッド, A.9

set_output_to_file, A.42

set_output_to_java, A.37

set_output_to_sql, A.32

set_preferenceメソッド, A.25

パーミッションの設定, 10.2.2

shortnameメソッド, 2.4.7, 2.6, A.2

show property, A.31

start_jmx_agent, A.58

uncompile_class, A.55

uncompile_method, A.57

unset_native_compiler_option, A.53

DBMS_JAVA query_output_to_java, A.41 DBMS_OUTPUTパッケージ, A.9 DbmsJavaクラス 「DBMS_JAVAパッケージ」を参照 DbmsObjectInputStreamクラス, 2.7.4 DbmsObjectOutputStreamクラス, 2.7.4 デッドロック, 2.11 DeadlockError例外, 2.11 デバッグ

コンパイラ・オプション, 2.4.1.4, 12.4

デバッグ

Javaストアド・プロシージャ, 5.4

パーミッション, 10.2.3

デフォルトのjava.securityリソース, 10.2.5 定義者権限, 2.4.6 deleteメソッド, 10.2.2.1 delete_permissionメソッド, A.24 derivedFromメソッド, A.7 DETERMINISTICに関するヒント, 6.3 ディレクトリ・コンテキスト, 11.2.2.1 disableメソッド, 10.2.2.1 disable_permissionメソッド, A.22 dropjavaメソッド, A.14 dropjavaツール, 2.4.4, 12.7

E

使いやすさ, 5.2.2

echoコマンド, 12.8.4.2

enableメソッド, 10.2.2.1

enable_permissionメソッド, A.23

カプセル化, 1.1.1.5

encoding

コンパイラ・オプション, 2.4.1.4, 12.4

コール終了時の移行, 2.12.1 EndOfCallRegistryクラス, 2.12.1

registerCallbackメソッド, 2.12.2

equalsメソッド, 10.2.1 エラー

コンパイル, 2.4.1.2

例外

ClassNotFoundException, 2.7

DeadlockError, 2.11

Oracle JVMによる処理方法, 7.6

LimboError, 2.11

exitコマンド, 12.8.4.2 exitCallメソッド, 2.11 export_classメソッド, A.11 export_resourceメソッド, A.12 export_sourceメソッド, A.10

F

フィールド

定義, 1.1.1.1

タイプ, 1.1.1.1

ファイル名

dropjavaツール, 12.7.3

loadjavaツール, 12.6.3

FilePermission, 10.2.2, 10.2.2.1, 10.2.2.1, 10.2.2.1, 10.2.2.1, 10.2.2.1 ファイル, 2.8.1

存続期間, 2.12.7

ファイナライザ, 2.8.2 fixed_in_instanceメソッド, A.8 フットプリント, 1.2.4, 2.1 外部キー, 8.1 forNameメソッド, 2.7 フルネーム, Java, 2.3 ファンクション, 5.1.1

G

ガベージ・コレクション, 2.1

リソース管理, 2.8

誤用, 2.8.2

ガベージ・コレクション

目的, 2.8.2

get_compiler_optionメソッド, 2.4.1.4, A.3 getCallerClassメソッド, 2.7.1 getClassLoaderメソッド, 2.7.1 getPropertyメソッド, 3.2 grantメソッド, 10.2.2.1 grant_permissionメソッド, 10.2.2.1, A.15, A.16 grant_policy_permissionメソッド, 10.2.2.1, 10.2.2.1, A.19, A.20 パーミッションの付与, 10.2.1 grantPolicyPermissionメソッド, 10.2.2.1 グラフィカル・ユーザー・インタフェース 「GUI」を参照 GUI, 1.3.3, 2.5

H

helpコマンド, 12.8.4.2

I

impliesメソッド, 10.2.1

継承, 1.1.1.3, 1.1.1.4

インストール, 4

統合開発環境(IDE), 1.3.4

整合性, 10.1

インタフェース, 1.1.1.4

JDBC内部ドライバ, 1.5.6

相互運用性, 5.2.5

インタプリタ, 1.5.3

IOException, 2.12.7

J

J2SE

インストール, 4.4.1

Java

アプリケーション, 2, 2.4.4

データベース・トリガーからのコール, 7.2

PL/SQLからのコール, 7.4

SQL DMLからのコール, 7.3

トップレベルからのコール, 7.1

コールに関する制限事項, 7.3

ロードされたクラスのチェック, 2.4.7

クラス, 1.1.1.1

クライアント設定, 4.4

コンパイル, 2.4.1

開発環境, 2.3

開発ツール, 1.6.5

実行制御, 2.2

データベースでの実行, 5.1

実行権限, 2.4.5

フィールド, 1.1.1.1

フルネーム, 2.3

データベース内, 1.2, 2

起動, 3.1

主な機能, 1.1.2

アプリケーションのロード, 2.4.4

クラスのロード, 2.2

メソッド, 1.1.1.1

概要, 1.1

ポリモフィズム, 1.1.1.6

公開, 2.3, 6

クラスの解決, 2.4.2

短縮名, 2.3

ストアド・プロシージャ 「ストアド・プロシージャ」を参照

Javaの監査

オブジェクト・レベル, 2.4.9

文レベル, 2.4.9

javaコマンド, 12.8.4.2 Java Compatibility Kit 「JCK」を参照 Java Database Connectivity 「JDBC」を参照 Java Development Kit 「JDK」を参照 .javaファイル, 2.3, 2.4.4, 2.4.4 Javaインタプリタ, 2.2 Java言語仕様 「JLS」を参照 Java Naming and Directory Interface 「JNDI」を参照 Javaネイティブ・インタフェース 「JNI」を参照 Javaセッションの初期化、期間およびエントリ・ポイント, 1.3.2 Javaストアド・プロシージャ 「ストアド・プロシージャ」を参照 Java仮想マシン 「JVM」を参照 JAVA$OPTIONS表, 2.4.1.4 JAVA_ADMIN

パーミッションの付与, 10.2, 10.2.1, 10.2.2.1, 10.2.2.1

JAVA_ADMINの例, 10.2.2.1 JAVA_ADMINロール

割り当てられたパーミッション, 10.2.2.1

java_jit_enabled, 9.1.1 JAVA_MAX_SESSIONSPACE_SIZEパラメータ, 9.2.1 JAVA_POOL_SIZEパラメータ, 9.2.1

デフォルト, 4.2

JAVA_SOFT_SESSIONSPACE_LIMITパラメータ, 9.2.1 Java2

セキュリティ, 10.2

Java2 Platform, Standard Edition 「Java SE」を参照 JAVADEBUGPRIVロール, 10.2.2.1, 10.2.3 JAVASYSPRIVロール, 10.2.1, 10.2.2.1, 10.2.2.2 JAVAUSERPRIVロール, 10.2.1, 10.2.2.1, 10.2.2.2 JCK, 1.1.3 JDBC, 1.1.2, 9.1

SQLへのアクセス, 1.6.4

定義済, 3.1.3

ドライバ, 1.5

ドライバ・タイプ, 1.6.4.1, 3.1.3.1

ドライバ, 1.6.4.1

例, 3.1.3.3

セキュリティ, 10.1

サーバー側内部ドライバ, 1.5.6

JDeveloper

開発環境, 1.6.5

JDK

インストール, 4.4.1

JIT

利点, 9.1.2

概要, 9.1.1

JLS, 1.1.1.1, 1.1.3 JNDI, 1.1.2 JNDIのサポート

概要, 11.1

要件, 11.2

ネームスペース, 11.2.1

ネームスペース・ブラウザ, 11.2.3

Oracle Java Directory ServiceのJNDIネームスペース・プロバイダ, 11.2.2

JNI

サポート, 3.1.2

JPublisher

概要, 13.3.4

JServerPermission, 10.2.2.1, 10.2.2.1, 10.2.2.1, 10.2.2.1, 10.2.3 Just-in-Timeコンパイラ 「JIT」を参照 JVM, 1.1.3

バイトコード, 1.1.3

構成, 4

定義済, 1.1

ガベージ・コレクション, 1.2.2, 1.2.3

インストール, 4

マルチスレッド, 1.2.2

役割, 2.1

K

キー

外部, 8.1

主, 8.1

L

ライブラリ・マネージャ, 1.5.1

LimboError例外, 2.11

ローダー, クラス, 1.5.4

ロード, 2.4.4

結果のチェック, 2.4.4, 2.4.7

クラス, 1.2.6, 2.2, 2.4, 2.4.4

コンパイル・オプション, 2.4.1

実行権限の付与, 2.4.5

JARファイルまたはZIPファイル, 2.4.4

必要な権限およびパーミッション, 2.4.4

クラスの再ロード, 2.4.4

制限, 2.4.4

loadjavaメソッド, A.13 loadjavaツール, 2.4.4, 12.6

ソースのコンパイル, 2.4.1.4, 9.2.4

例, 3.1.1, 5.3.2

実行権限, 2.4.5, 10.2

クラスのロード, 2.4.4

解決モード, 12.3

メモリーの使用, 9.2.1

ロギング, 2.4.3 logging.properties, 2.4.3 LogManager, 2.4.3 longnameメソッド, 2.4.7, 2.6, A.1 lookupClassメソッド, 2.7.3

M

mainメソッド, 2.2

メンテナンス性, 5.2.4

マップ・メソッド, 6.5.2.1

メモリー

複数コール, 2.8.2

コール, 2.1

Javaプール, 9.2.2

リーク, 2.8.2

存続期間, 2.8.1, 2.12.7

パフォーマンス構成, 9.2

セッション, 2.1

メソッド, 1.1.1.1, 5.1.3, 6.5

コンストラクタ, 6.5.2.2

宣言, 6.5.2

マップおよびオーダー, 6.5.2.1

オブジェクト・リレーショナル, 5.1.3

欠落しているクラス, 12.6.2 モード

パラメータ, 6.2.1

複数継承, 1.1.1.4 複数のJDKのサポート, 1.6.7

既存のデータベースを使用する, 1.6.7.2

既存のデータベースを使用しない, 1.6.7.1

マルチスレッド, 1.2.2

N

NAME句, 6.3

ネームスペース, 12.8

ネイティブ・コンパイル

メソッド, 1.2.5

パフォーマンス, 1.2.5

ネイティブJavaインタフェース, 3.1.5 NetPermission, 10.2.2.1, 10.2.2.1

O

オブジェクト, 1.1.1.2

フルネームから短縮名への変換, 2.4.7

存続期間, 2.12.7

スキーマ, 2.3

シリアライズ, 2.7.4

SQL型, 5.1.3

表, 6.5.2.3

コール仕様の記述, 6.5

ObjectFactory, 11.2.2.3 ObjectInputStreamクラス, 2.7.4 ObjectOutputStreamクラス, 2.7.4 オブジェクト・リレーショナル・メソッド, 5.1.3 OJDS, 11.1

APIおよびクラス, 11.4

コマンドライン・ツール, 11.3

bind, 11.3.10

bindds, 11.3.11

bindurl, 11.3.12

cd, 11.3.2

chmod, 11.3.9

chown, 11.3.4

ln, 11.3.7

ls, 11.3.1

mkdir, 11.3.5

mv, 11.3.8

pwd, 11.3.3

rm, 11.3.6

OJDS URLのサポート, 11.2.2.4 ojvmjavaツール, 12.8 online

コンパイラ・オプション, 2.4.1.4, 12.4

オペレーティング・システム

リソース, 2.8

オペレーティング・システム・リソース

アクセス, 2.8.1

複数コール, 2.12.7

クローズ, 2.8.2

ガベージ・コレクション, 2.8.2

存続期間, 2.8.1

管理, 2.8

概要, 2.8.1

パフォーマンス, 9.2

Oracle Java Directory Service, 11.1 Oracle JVM

クラス・ローダー, 1.5.4

コンパイラ, 1.5.2

構成要件, 4.2

インタプリタ, 1.5.3

JDBC内部ドライバ, 1.5.5, 1.5.6

ライブラリ・マネージャ, 1.5.1

主要コンポーネント, 1.5

SQLJトランスレータ, 1.5.7

検証機能, 1.5.5, 1.5.5

Oracle Net Services Connection Manager, 1.2.1 oracle.aurora.jndi.ojds.OjdsClientContext, 11.4.1 oracle.aurora.jndi.ojds.OjdsInitialContextFactory, 11.4.3 oracle.aurora.jndi.ojds.OjdsServerContext, 11.4.2 oracle.aurora.jndi.ojds.OjdsURLContext, 11.4.5 oracle.aurora.jndi.ojds.OjdsURLContextFactory, 11.4.4 OracleRuntimeクラス

exitCallメソッド, 2.11, 2.11

getCallerClassメソッド, 2.7.1

getClassLoaderメソッド, 2.7.1

オーダー・メソッド, 6.5.2.1 出力

リダイレクト, 3.3, 7.1.1

P

パッケージDBMS_JAVA, 4.3, 7.1.1

パッケージ化されたコール仕様, 記述, 6.4

PARALLEL_ENABLEオプション, 6.3

パラメータ・モード, 6.2.1

パフォーマンス, 5.2.1, 9

ネイティブ・コンパイル, 1.2.5

パーミッション

Oracle固有, 10.2.2.1

タイプ, 10.2.2.1

パーミッション・クラス, 10.2.2, 10.2.2.1, 10.2.2.1, 10.2.2.1, 10.2.2.1 パーミッション, 10.1

管理, 10.2.2.1

割当て, 10.2.1, 10.2.2

作成, 10.2.2.1

デバッグ, 10.2.3

削除, 10.2.2.1

使用禁止, 10.2.2.1

使用可能, 10.2.2.1

付与, 10.2.1, 10.2.2.1

ポリシーの付与, 10.2.2.1, 10.2.2.1

付与, 例, 10.2.2.1

ロールにグループ化, 10.2.2.2

JAVA_ADMINロール, 10.2.2.1

JAVADEBUGPRIVロール, 10.2.2.1

JAVASYSPRIVロール, 10.2.2.1

JAVAUSERPRIVロール, 10.2.2.1

制限, 10.2.1, 10.2.2.1, 10.2.2.1

制限, 例, 10.2.2.1

PUBLIC, 10.2.2.1

制限, 10.2.1, 10.2.2.1

制限, 例, 10.2.2.1

ポリシーの指定, 10.2.1

SYSパーミッション, 10.2.2.1

タイプ, 10.2.2.1

PL/SQL

Javaのコール, 7.4

パッケージ, 6.4

ポリシー表

管理, 10.2.2.1

変更, 10.2.2

パーミッションの設定, 10.2.2

表示, 10.2.2

PolicyTableクラス

ポリシーの指定, 10.2.1

更新, 10.2.1, 10.2.2.1

PolicyTableManagerクラス

deleteメソッド, 10.2.2.1

disableメソッド, 10.2.2.1

enableメソッド, 10.2.2.1

PolicyTablePermission, 10.2.2, 10.2.2.1, 10.2.2.1, 10.2.2.1 ポリモフィズム, 1.1.1.6 主キー, 8.1 権限

データベース, 10.2

プロシージャ, 5.1.1 生産性, 5.2.2 .propertiesファイル, 2.3, 2.4.4, 2.4.4 PropertyPermission, 10.2.2.1, 10.2.2.1, 10.2.2.2 PUBLICパーミッション, 10.2.2.1 公開, 2.2, 2.4, 2.4.8

例, 3.1.1, 5.3.3

R

出力のリダイレクト, 3.3, 7.1.1

REF, 6.5.2.3

ReflectPermission, 10.2.2.1, 10.2.2.1

registerCallbackメソッド, 2.12.2

レプリケーション, 5.2.6

reset_compiler_optionメソッド, 2.4.1.4, A.5

リゾルバ, 2.4.2, 12.3, 12.3

デフォルト, 2.4.2

定義済, 2.3, 2.4, 2.7

例, 3.1.1, 5.3.2

存在しない参照を無視, 2.4.2, 2.4.2

resolverメソッド, A.6 リゾルバ仕様

定義, 2.4.2

リソース・スキーマ・オブジェクト, 2.4.4, 2.4.4, 2.4.4, 12.1 restrictメソッド, 10.2.2.1 restrict_permissionメソッド, 10.2.2.1, 10.2.2.1, A.17, A.18 revokeメソッド, 10.2.2.1 revoke_permissionメソッド, 10.2.2.1, A.21 行トリガー, 7.2 ランタイム・コンテキスト, ストアド・プロシージャ, 5.1 Runtime.exec, 2.9 RuntimePermission, 10.2.2.1, 10.2.2.1, 10.2.2.1

S

スケーラビリティ, 5.2.3

スキャベンジ, 1.2.3

セキュリティ, 5.2.7

SecurityPermission, 10.2.2.1, 10.2.2.1

.serファイル, 2.3, 2.4.4, 2.4.4

SerializablePermission, 10.2.2.1, 10.2.2.1

セッション, 1.3

ネームスペース, 12.8

セッション・メモリー, 2.1 set_compiler_optionメソッド, 2.4.1.4, A.4 set_outputメソッド, A.9 set_preferenceメソッド, A.25 SHARED_POOL_SIZEパラメータ, 9.2.1

デフォルト, 4.2

シェル・コマンド, 12.8.4.2 短縮名, Java, 2.3 shortnameメソッド, A.2 単一の継承, 1.1.1.3 SocketPermission, 10.2.2.1, 10.2.2.1, 10.2.2.1 ソース・スキーマ・オブジェクト, 2.4.4, 2.4.4, 2.4.4, 12.1 SQLJ

サーバー側トランスレータ, 1.5.7

トランスレータ, 1.5.7

.sqljファイル, 2.3, 2.4.4, 2.4.4 start_jmx_agent, A.58 StateFactory, 11.2.2.2 文トリガー, 7.2 ストアド・プロシージャ

利点, 5.2

コール, 7

定義済, 1.6.2, 1.6.3

開発, 5, 8

例, 8

概要, 5

起動, 3.1

公開, 6

手順, 5.3

T

スレッド

モデル, 1.2.2, 2.11

スレッド

複数コール, 2.12.7

ライフ・サイクル, 2.11

Oracle JVM, 2.8.1

Oracle Databaseのスレッド, 2.11

トップレベルのコール仕様, 記述, 6.3 トリガー

Javaのコール, 7.2

データベース, 5.1.2, 7.2

行, 7.2

文, 7.2

Javaストアド・プロシージャの使用, 3.1.1, 5.3

U

ユーザー・インタフェース, 2.5

USER_ERRORS, 2.4.1.2

USER_JAVA_POLICYビュー, 10.2.2, 10.2.2.1, 10.2.2.1

USER_OBJECTS, 2.4.4, 2.4.7, A.2

アクセス, 例, 2.4.7

V

V$SGASTAT表, 9.2.3

変数

静的, 2.1

検証機能, 1.5.5 バージョン

取得, 3.2

versionコマンド, 12.8.4.2

W

Webサービス

データベースのコール, 13.2.1

データベースからのコール, 13.3.1, 13.3.2

JPublisherによるコールのサポート, 13.2.3

Oracle Databaseの機能, 13.2.2, 13.2.2, 13.3.3

概要, 13.1

サービス・コンシューマ, 13.3

サービス・プロバイダ, 13.2

コールでのJPublisherの使用, 13.2.1

動作方向, 13.1

whoamiコマンド, 12.8.4.2

オラクル社の法律上の注意点について

コピーライトについて

Copyright © 1994-2015, Oracle and/or its affiliates.All rights reserved.

商標と登録商標について

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

ライセンス制約の保証と結果的に生じる損害の免責

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

保証免責

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

制限付権利

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

危険な用途への使用について

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション（人的傷害を発生させる可能性があるアプリケーションを含む）への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性（redundancy）、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

第三者のコンテンツ、製品、サービスに対する免責事項

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

ドラフトのアルファ版およびベータ版ドキュメントについて

このドキュメントが試作版の場合:

このドキュメントは試作版であり、デモおよび暫定使用のみを目的としたものです。このソフトウェアを使用するハードウェアに限定するものではありません。オラクル社およびその関連会社は、このドキュメントに関して一切の責任を負わず、いかなる保証もいたしません。また、このドキュメントを使用したことによって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。