ナビゲーションをスキップ

Java アプリケーションの開発

  前 次 前/次ボタンと目次ボタンとの区切り線 目次  

推奨されるコーディングのプラクティス

この節では、BEA JRockit で実行するアプリケーションを記述するためのガイドラインを示します。ここで提供する情報は包括的なものではありませんが、一般的な落とし穴を回避するのに役立ちます。BEA Systems は Java の「write once run everywhere」という概念を妥協することはありません。この節では、どの Java プログラムにとっても有用なガイドラインを示しますが、これらのガイドラインは、概して JVM 同士、特に Sun Microsystems の HotSpot JVM と BEA JRockit JVM の間で切り替えを行うときに非常に重要です。

ベスト プラクティスのコーディングの内容は以下のとおりです。

 


関連する仕様を読む

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

BEA JRockit JVM は Java 仮想マシン仕様や Java API 仕様などのさまざまな仕様に基づいています。これらの仕様には多数の実装があり、BEA JRockit JVM もその 1 つです。これらの仕様で規定されていない特別の動作は想定しないようにする必要があります。規定されていない動作は Sun JVM と BEA JRockit JVM で異なることがあります。また、Sun JVM の個々のリリースや、BEA JRockit JVM のリリースによっても異なる場合があるので注意が必要です。

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

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

例 1: リフレクション

java.lang.ClassgetMethods() メソッドに関する Java API 仕様では、「返された配列内の要素は、ソートされていたり、特定の順序になっていることはありません」と明記されています。

例 2: リフレクション (2)

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

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

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

 


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

以下のメソッドは非推奨です。

上記のメソッドは本質的に安全ではないため、使用しないでください。詳細については、以下を参照してください。

http://java.sun.com/j2se/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

 


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

ファイナライザは実行の順序に暗黙的に依存することがよくあるため、エラーが発生しやすくなります。この順序は JVM 間でも、同じ JVM 上の連続した実行同士でも異なります。また、ファイナライザを使用すると、メモリ管理システムはファイナライザの実行を処理し、オブジェクトをより長くアクティブにしておく必要があり、余分な負荷がかかるため、本質的にパフォーマンスによくありません。ファイナライザの使用方法 (および使用しない方法) の詳細については、以下を参照してください。

http://access1.sun.com/techarticles/weak.references.html

http://www.memorymanagement.org/glossary/r.html#reference.object

 


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

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

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

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

 


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

BEA JRockit JDK に含まれるクラスは、java.*javax.*org.*sun.* および COM.jrockit.* の各パッケージ グループに分類されます。sun.* および COM.jrockit パッケージ以外は Java プラットフォームの標準部分であり、今後もサポートされます。一般に、Java プラットフォームに含まれていない非標準のパッケージは、JVM ベンダと OS プラットフォーム (Windows、Linux など) によって異なることがあり、JDK のバージョンごとに予告なくいつでも変更される可能性があります。sun.* および COM.jrockit.* パッケージの直接の使用が含まれるプログラムは 100% Pure Java ではありません。

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

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

 


java.util.Hashtable を使用する場合はユーザ定義クラスの java.Object.hashCode をオーバーライドする

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

 


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

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

 


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

java.lang.System.getProperties() または java.lang.System.getProperty() を実装する場合は、返される標準のシステム プロパティにのみ依存する必要があります。VM が異なると、拡張プロパティの別のセットを返す可能性があります。非標準のプロパティが返されないようにしてください。

JVM は起動時に、システム プロパティ リストに多数の標準プロパティを挿入します。これらのプロパティとその値の意味は、Java API 仕様で示されています。これ以外の非標準のプロパティを想定しないようにしてください。

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html

 


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

アプリケーションを設計するときに、複数のプロセス (JVM インスタンス) を実行するか、単一のプロセス (JVM インスタンス) の内部で複数のスレッドまたはスレッド グループを実行するかを選ぶ場合があります。可能な場合は、1 つの物理マシンごとにできる限り少ない JVM インスタンスを使用する方が効率的です。

 


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

java.lang.System.gc() を呼び出さないでください。このメソッドは BEA JRockit JVM と他の JVM とでは動作が異なります。Sun JVM や他の JVM のように完全なガベージ コレクションを行う代わりに、BEA JRockit JVM で動作するアプリケーションによって呼び出される場合、System.gc() は既に使用中のガベージ コレクタによって動作が異なります。

注意 : System.gc() を呼び出す必要がある場合は、コマンドライン オプション -XXfullsystemgc を使用して、BEA JRockit JVM の動作をオーバーライドするとよいでしょう。

一般に、BEA JRockit JVM のガベージ コレクタは、ガベージ コレクションの実行時期を System.gc() よりも効果的に決定します。メモリ使用状況やガベージ コレクションの休止時間などで問題がある場合は、BEA JRockit JVM のメモリ管理システムを適切にコンフィグレーションしてください。「BEA JRockit JVM のチューニング」を参照してください。

 

ナビゲーション バーをスキップ  ページの先頭 前 次