ヘッダーをスキップ
Oracle® JRockitアプリケーション開発ガイド
リリースR28
B61442-01
 

 

Oracle® JRockit

アプリケーション開発ガイド

リリースR28

B61442-01(原本部品番号:E15063-03)

2010年11月

このドキュメントでは、Oracle JRockit JVMで実行するJavaアプリケーションを記述するためのガイドラインを示します。このガイドラインは、JVM間全般、および特にHotSpot JVMとJRockit JVMの間で切り替えを行う場合に非常に重要です。

このドキュメントの構成は次のとおりです。

1 関連する仕様を読む

Java言語およびJava APIの仕様をよく読み、規定されていない動作には依存しないようにします。

Oracle JRockit JDKは、Java仮想マシン仕様やJava API仕様などの様々な仕様に基づいています。

これらの仕様は以下のサイトにあります。

これらの仕様には多数の実装があり、JRockit JDKもその1つです。これらのドキュメントで指定されていない特別の動作は想定しないようにします。指定されていない動作はHotSpot JDKとJRockit JDKで異なることがあります。HotSpot JDKの個々のリリース、またはJRockit JDKのリリースによって異なる場合があるので注意が必要です。

仕様では、JDKベンダにJDKを最適化する自由を与えているため、規定されていない特定の動作があります。前述の仕様には規定されていない部分が多数あることを理解しておく必要があります。以下の例で、そのような規定されていない要素を4つ紹介します。

1.1 例1: リフレクション

java.lang.ClassクラスのgetMethods()メソッドに関するJava API仕様では、返された配列内の要素は、ソートされておらず、特定の順序に並べられていないと明記しています。

1.2 例2: リフレクション再考

java.lang.reflect.MethodクラスのtoString()メソッドではアクセス修飾子nativeを使用できます。そのため、この呼出しの結果がJVM実装同士で同じであるということに依存しないでください。Java API仕様のクラスの一部にはJRockit JDKまたはHotSpot JDKのどちらかでnativeとして実装されているものがあります。あるJVMのネイティブ実装が別のJVMでもネイティブであるという保証はありません。

1.3 例3: シリアライゼーション

java.lang.ObjectInputStreamクラスのdefaultReadObject()メソッドに関するJava API仕様では、デシリアライズされるフィールドの順序が規定されていないため、このような順序を予期することはできません。

1.4 例4: ファイナライザ

JVM仕様には、finalizeメソッドをオーバーライドするクラスでは、オブジェクトに対するガベージ・コレクションの実行前に必ずfinalizeメソッドが実行される、と記述されています。実際にどの時点でファイナライザを実行するかの判断は各JVM実装に任されています。ガベージ・コレクションの対象となることがまったくないオブジェクトでは、ファイナライザは1回も実行されません。そのため、アプリケーションでは、ファイナライザが実行されるという前提で、ソケットやその他のファイル・ハンドルなど、特定のリソースの解放処理をファイナライザに任せていると、様々な種類のリソース不足の問題が発生するおそれがあります。

JRockit JVMでは、独立したスレッドでファイナライザの実行を処理します。ファイナライザが独立したスレッドで実行される場合、次のような2つの状況が生じます。

  • オブジェクトを作成したスレッドとは別のスレッドによってファイナライザが呼び出されます。

  • 一度に1つのファイナライザのみが処理されます。ファイナライザがブロックされる場合、または完了するのに時間がかかる場合、他のファイナライザの呼出しが遅延します。

アプリケーションがSystem.runFinalization()メソッドを呼び出すと、2番目のファイナライザ・スレッドが作成されます。これにより、1番目のファイナライザ・スレッドが未処理のファイナライザを呼び出せるようになるため、ガベージ・コレクタによってアクセスできないと判断されてからファイナライザが実行されるまでの時間を短縮することができます。保留中のファイナライザがなくなると、2番目のファイナライザ・スレッドは終了します。この2番目のファイナライザは通常の優先順位で開始されます。

ファイナライザが通常のロックのために競合している場合、2番目のファイナライザ・スレッドを作成すると、パフォーマンスが低下するおそれがあります。

2 非推奨の安全でないメソッドを使用しない

すでに非推奨となっている多数のメソッドは本質的に安全ではないため、使用しないでください。コンパイル時に-deprecationオプションを指定すると、非推奨のメソッドが使用されているメソッドを確認することができます。非推奨のメソッドの詳細は、以下を参照してください。

3 ファイナライザの使用を最小限に抑える

ファイナライザは実行の際に暗黙的に順序に依存することがよくあるため、エラーが発生しやすくなります。この順序はJVM間でも、同じJVM上の連続した実行同士でも異なります。ファイナライザを使用すると、ファイナライザの実行を処理し、オブジェクトをアクティブな状態で維持するためにメモリー管理システムに余分な負荷がかかるため、パフォーマンスが低下する可能性があります。

ファイナライザの詳細は、http://www.memorymanagement.org/glossary/r.html#reference.objectを参照してください。

4 スレッドの優先順位に依存しない

java.lang.Thread.setPriorityメソッドを使用する場合は注意してください。スレッドの優先順位に依存すると、望まないまたは予期しない結果を引き起こす可能性があります。それは、スケジューリング・アルゴリズムが、優先順位の低いスレッドに十分なCPU時間を割り当てない、またはそのスレッドを永久に実行しない可能性があるためです。さらに、その結果はオペレーティング・システムやJVM間で異なる場合があります。

Java API仕様には、すべてのスレッドに優先順位が付けられ、優先順位の高いスレッドは、優先順位の低いスレッドよりも優先して実行されると記述されています。

setPriority()メソッドによって設定される優先順位は、スレッド・スケジューリング・アルゴリズムで使用されるパラメータであり、CPU時間を実行スレッドに分配するものです。このアルゴリズムはJVMまたはオペレーティング・システムによって制御されます。このアルゴリズムは通常、オペレーティング・システム間で異なり、オペレーティング・システムとJVMの各リリース間でも異なる場合があることを認識していることが大切です。

5 内部的なsun.*またはjrockit.*クラスを使用しない

Oracle JRockit JDKに含まれるクラスは、bea.*、java.*javax.*org.*sun.*com.bea.jvm.*およびjrockit.*の各パッケージにグループ分けされています。sun.*jrockit.*およびcom.bea.jvm.*パッケージ以外はJavaプラットフォームの標準部分であり、サポートされています。com.bea.jvm.*パッケージのクラスには、公式にサポートされているクラスやドキュメントに情報が記載されているクラスだけでなく、サポート対象外の内部的なクラスも含まれています。ここでは、ドキュメントに記載されていないcom.bea.jvm.*のクラスに関する情報を取り上げています。一般に、Javaプラットフォームに含まれていない非標準のパッケージは、JVMベンダとオペレーティング・システム(Windows、Linuxなど)によって異なることがあり、JDKのバージョンごとに予告なくいつでも変更される可能性があります。sun.*およびjrockit.*パッケージを直接使用しているプログラムは完全にはJavaではありません。

詳細は、以下のsun.*パッケージに関する注意を参照してください。

http://java.sun.com/products/jdk/faq/faq-sun-packages.html

6 ハッシュ化を使用する場合はユーザー定義クラスのjava.Object.hashCodeをオーバーライドする

JRockit JVMにおけるhashcodeの現在のデフォルト実装では、JVMによって決定された値がオブジェクトの値として返されます。値はオブジェクトのメモリー・アドレスを使用して作成されます。ただし、ガベージ・コレクション中にオブジェクトが移動される場合、この値は再利用できるため、2つの異なるオブジェクトに対する同じハッシュ・コードを取得することが可能です。また、同じ値を表す2つのオブジェクトは、まったく同一のオブジェクトである場合にのみ同じハッシュ・コードを持つことが保証されています。この実装はハッシュ化を行う上ではあまり便利ではありません。そのため、クラスのオブジェクトをjava.util.Hashtableまたはjava.util.HashMapクラスに格納する必要がある場合は、派生クラスでhashCode()メソッドをオーバーライドしてください。

7 スレッドの同期は慎重に行う

共有データにアクセスするスレッドは、同期化されている必要があります。JVMを変更すると同期化のバグが発生することがよくあります。ロック、ガベージ・コレクション、スレッド・スケジューリングなどの実装が大きく異なる可能性があるためです。


注意:

同期化の問題(デッドロックや競合状態)の原因がコードに含まれている場合、そのバグは他のJVMを使用していた時点ですでに存在していたと考えられます。他のJVMの使用時に同様の同期化の問題が発生したことがなかったならば、それは純然たる偶然です。

8 標準のシステム・プロパティのみを想定する

java.lang.System.getProperties()またはjava.lang.System.getProperty()メソッドを呼び出す場合は、標準のシステム・プロパティのみが返されることを想定してください。VMが異なると、拡張プロパティの別のセットを返す可能性があります。非標準のプロパティが返されないようにしてください。

JVMは起動時に、システム・プロパティ・リストに多数の標準プロパティを挿入します。これらのプロパティとその値の意味は、Java API仕様にリストされています。これ以外の非標準のプロパティに依存しないでください。これらのAPIの詳細は、以下を参照してください。

9 Javaプロセスの数を最小限に抑える

アプリケーションを設計するときに、複数のプロセス(JVMインスタンス)を実行するか、単一のプロセス(JVMインスタンス)の内部で複数のスレッドまたはスレッド・グループを実行するかを選択できます。ほとんどの場合、各コンピュータで使用するJVMインスタンス数を最小限に抑えるほうが効率的です。

10 System.gc()を呼び出さない

java.lang.System.gc()メソッドを呼び出さないでください。System.gc()メソッドを呼び出すよりも、JRockit JVMのガベージ・コレクタにガベージ・コレクションの実行時期を決定させるほうが効果的です。実際、アプリケーションがSystem.gc()メソッドを繰返し呼び出すと、パフォーマンスが低下する可能性があります。メモリー使用状況やガベージ・コレクションの休止時間などで問題がある場合は、JRockit JVMのメモリー管理システムを適切に構成してください。パフォーマンスのチューニングの詳細は、Oracle JRockitパフォーマンス・チューニング・ガイドを参照してください。

このメソッドは、JRockit JVMと他のJVMとでは動作が異なる可能性があります。JRockit JVMでSystem.gc()メソッドを呼び出すと、世代別ガベージ・コレクタを使用している場合はナーサリのコレクションが実行され、一世代のコレクタの場合は古い領域のコレクションが実行されます。

以下の3つのコマンドライン・オプションにより、System.gc()メソッドの動作を変更できます。

11 オブジェクトの割当ては慎重に行う

オブジェクトの割当ては、ガベージ・コレクションを引き起こします。可能な場合は、オブジェクトの割当てと再割当てを行わないようにします。たとえば次のような場合です。

12 ネイティブ・コード(JNI)のシグナルは慎重に使用する

JRockit JVMでは、様々な目的で内部的にシグナルが使用されています。シグナルを使用するネイティブ・ライブラリ(Javaネイティブ・インタフェース)を使用する場合は、次のガイドラインに従う必要があります。

12.1 シグナル・チェーンを使用する

Javaで実行されるコード内でシグナルを利用する場合はシグナル・チェーンを使用する必要があります。シグナル・チェーンの機能を使用すると、独自のシグナル・ハンドラをインストールするネイティブ・コードとJavaの相互運用性を高めることができます。シグナル・チェーンを実現するには、リンク時にlibjsig.soをリンクする方法と、実行時にLD_PRELOAD環境変数を使用する方法があります。これらのチェーンの設定方法の詳細は、次のURLでシグナル・チェーンに関するJavaドキュメントを参照してください。

12.2 SIGUSR1およびSIGUSR2を使用しない

JRockit JVMでは、SIGUSR1およびSIGUSR2の2つのシグナルがJVMの内部的な目的で使用されています。これらのシグナルはOracle JRockit JVMの機能にとって不可欠の重要な要素であり、無効にはできません。そのため、ユーザーのネイティブ・ライブラリではSIGUSR1シグナルは使用しないでください。これらのシグナルの使用はJVMの障害につながり、多くの場合、シグナルを受信したスレッドのハング(SIGUSR1の場合)やJVMのクラッシュ(SIGUSR2の場合)が発生する原因となります。

12.3 シグナルを受信する場合があるという前提で確認を行います(EINTRをチェックします)

システム・ルーチン(sleepなど)を呼び出すネイティブ・コードでは、errnoの値がEINTRに設定され、失敗の戻り値(-1)が返されていないかを確認する必要があります。この値が設定されている場合は、通常、そのシステム・ルーチンの呼出しを再試行します(一部例外があるので、実際に使用しているシステムのプログラミング・マニュアルで確認してください)。JRockit JVMは、アタッチされているスレッドに対して定期的な間隔でSIGUSR1シグナルを送信します。このため、コード内のあらゆる箇所でシグナルを受信する可能性があります。

12.4 -Xrsが必要かどうかを十分に検討する

-Xrs(シグナルの削減)コマンドライン・オプションを指定すると、SIGINTSIGTERMSIGHUPおよびSIGQUITに対するシグナル・マスクはJVMによって変更されず、これらのシグナルのシグナル・ハンドラはインストールされません。-Xrsを指定すると、結果的に以下の2つの影響が生じます。

  • SIGQUITスレッド・ダンプが利用できなくなります。

  • 停止フックの実行は、JVMが終了するときにSystem.exit()メソッドを呼び出すなどして、ユーザー・コード側で行う必要があります。

JVMによるオペレーティング・システムのシグナルの使用が減るため、このオプションはシグナルの削減と呼ばれます。

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

オラクル社は、障害のあるお客様にもオラクル社の製品、サービスおよびサポート・ドキュメントを簡単にご利用いただけることを目標としています。オラクル社のドキュメントには、ユーザーが障害支援技術を使用して情報を利用できる機能が組み込まれています。HTML形式のドキュメントで用意されており、障害のあるお客様が簡単にアクセスできるようにマークアップされています。標準規格は改善されつつあります。オラクル社はドキュメントをすべてのお客様がご利用できるように、市場をリードする他の技術ベンダーと積極的に連携して技術的な問題に対応しています。オラクル社のアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイトhttp://www.oracle.com/accessibility/を参照してください。

ドキュメント内のサンプル・コードのアクセシビリティについて

スクリーン・リーダーは、ドキュメント内のサンプル・コードを正確に読めない場合があります。コード表記規則では閉じ括弧だけを行に記述する必要があります。しかし一部のスクリーン・リーダーは括弧だけの行を読まない場合があります。

外部Webサイトのドキュメントのアクセシビリティについて

このドキュメントにはオラクル社およびその関連会社が所有または管理しないWebサイトへのリンクが含まれている場合があります。オラクル社およびその関連会社は、それらのWebサイトのアクセシビリティに関しての評価や言及は行っておりません。

Oracleサポートへのアクセス

Oracleのお客様は、My Oracle Supportにアクセスして電子サポートを受けることができます。詳細は、http://www.oracle.com/support/contact.html、聴覚に障害のあるお客様はhttp://www.oracle.com/accessibility/support.htmlを参照してください。


Oracle JRockitアプリケーション開発ガイド, リリースR28

B61442-01

Copyright c 2007, 2010, Oracle and/or its affiliates. All rights reserved.

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

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

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

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

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

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

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