クラス・ロード例外

クラス・ロード例外エラーは、問題の判別に役立ちます。

アプリケーションの開発時、あるいはインストール済みアプリケーションの開始時に発生するクラス・ロード・エラーの種類を特定してください。

ClassCastException

クラス・キャスト例外は、以下の条件が存在する場合に発生し、次のアクションによって修正することができます。

ソース・オブジェクトのタイプは、 ターゲット・クラス (タイプ) のインスタンスではありません。
これは、典型的なクラス・キャスト例外です。 キャスト・ステートメントの ソース・オブジェクトがターゲット・クラス (タイプ) のインスタンスではないと診断するには、ソース・オブジェクト・クラスのクラス・シグニチャーを調査し、その先祖にターゲット・クラスを含まないこと、およびソース・オブジェクト・クラスが、ターゲット・クラスと異なることを確認します。 クラス情報を取得するには、単純な print ステートメントをコードに挿入します。 以下に例を示します。
System.out.println( source.getClass().getName() + “:” + target.getClass().getName() );
または、javap コマンドを使用します。 以下に例を示します。
javap java.util.HashMap
Compiled from "HashMap.java"
public class java.util.HashMap extends java.util.AbstractMap
             implements java.util.Map,java.lang.Cloneable,java.io.Serializable {
ソース・オブジェクト (クラス) をロードするクラス・ローダーが、ターゲット・クラスをロードするクラス・ローダーと異なります。
ソース・オブジェクトのタイプがターゲット・クラスのインスタンスであるとすると、 クラス・キャスト例外が発生するのは、ソース・オブジェクトのクラスをロードするクラス・ローダーが、ターゲット・クラスをロードするクラス・ローダーと異なる場合です。 この状態は、ターゲット・クラスが WebSphere® Application Server ランタイム環境内の複数のクラス・ローダーのクラスパスで可視である場合に発生する可能性があります。 この問題を訂正するには、クラス・ローダーの問題を診断するのに使う「検索」および「クラス名で検索 (Search by class name)」コンソール・ページを使用します。
  1. トラブルシューティング > 「クラス・ローダー・ビューアー」 > module_name > 「検索」 をクリックして、 「検索」ページにアクセスします。
  2. 「検索タイプ」「クラス/パッケージ」」を選択します。
  3. 「検索語」に、2 つのクラス・ローダーによってロードされるクラスの名前を入力します。
  4. OK」をクリックします。 「クラス名で検索 (Search by class name)」ページが表示され 、クラスをロードするすべてのクラス・ローダーがリストされます。

    複数のクラス・ローダーがリストされた場合は、ターゲット・クラスが複数のクラス・ローダーによってロードされています。 ソース・オブジェクトはターゲット・クラスのインスタンスであるため、 ソース・オブジェクト・クラスをロードするクラス・ローダーが、ターゲット・クラスをロードするクラス・ローダーと異なります。

  5. クラス・ローダー・ビューアー・ページ に戻り、クラスパスを調べて、2 つの異なるクラス・ローダーがクラスをロードした理由を判別してください。
  6. 該当するクラス・ローダーのみにクラスが見えるように、コードを修正します。
アプリケーションが、 絞り込み操作を実行しないか、または実行が不適切です。
クラス・キャスト例外は、アプリケーションがリモート・エンタープライズ Bean (EJB) オブジェクトを解決しているときに、 アプリケーション・コードが必要な絞り込み操作を実行しないために起こります。 アプリケーションは、リモート・オブジェクトを検索した後で絞り込み操作を実行する必要があります。 アプリケーションを調査し、アプリケーションがリモート・オブジェクトを検索するかどうかを判別し、検索する場合には、検索の結果を絞り込みメソッドに送信します。

絞り込みメソッドは、EJB 2.0 プログラミング・モデルに従って呼び出される必要があります。 特に、絞り込みメソッドに送信されるターゲット・クラスは、EJB の正確な最派生インターフェースでなければなりません。 これにより、 WebSphere Application Server ランタイム環境でクラス・キャスト例外も発生します。 アプリケーションを調査し、絞り込みメソッドに送信されるターゲット・クラスが、 正確な EJB タイプではなく、指定された EJB のスーパー・インターフェースとなっていないか判別します。そうである場合は、正確な EJB インターフェースで絞り込みを呼び出すようにアプリケーションを修正します。

最後に、絞り込み操作中に クラス・キャスト例外が発生する場合は、絞り込みメソッドが、ローカル・エンタープライズ Bean ではなく、 リモート EJB の検索結果に適用されていることを確認します。 絞り込みは、ローカル検索には使用されません。 アプリケーションまたはモジュールのデプロイメント記述子を検査して、絞り込み検索対象のオブジェクトがローカル・オブジェクトでないことを確認します。

ClassNotFoundException

class not found exception は、以下の条件が存在する場合に発生し、次のアクションを実行するこ とによって修正できます。

クラスが コンテキスト・クラス・ローダーの論理クラスパスで可視ではありません。
見つからないクラスは、現在のスレッドに関連付けられている クラス・ローダーの論理クラスパスに存在しません。 論理クラスパスは、ロード操作がクラス・ローダーで呼び出されたときに検索されるすべてのクラスパスの累積です。 この問題を修正するには、「検索」ページを使用して、クラス名と Java™ アーカイブ (JAR) 名で検索します。
  1. トラブルシューティング > 「クラス・ローダー・ビューアー」 > module_name > 「検索」 をクリックして、 「検索」ページにアクセスします。
  2. 「検索タイプ」「クラス/パッケージ」」を選択します。
  3. 「検索語」に、見つからないクラス名を入力します。
  4. OK」をクリックします。 「クラス名で検索 (Search by class name)」ページが表示され 、クラスをロードするすべてのクラス・ローダーがリストされます。
  5. ページを調べてそのクラスがリストに存在しているかどうか確認します。
  6. リストにそのクラスがない場合は、「検索」ページに戻ります。 「検索語」に、クラスの .jar ファイルの名前を入力し、「検索タイプ」「JAR/ディレクトリー (JAR/Directory)」を選択します。
  7. OK」をクリックします。 「Search by Path」ページが表示され、JAR ファイルを格納しているすべてのディレクトリーがリストされます。

JAR ファイルがリストにない場合、そのクラスは論理クラスパスにないか、読み取り不能か、代替クラスが既にロードされている場合があります。 クラスを、ロードできるロケーションに移動します。

アプリケーションが クラス・ローダー API を間違って使用します。
アプリケーションは、クラス・ローダーのインスタンスを取得し、 そのクラス・ローダーの loadClass メソッドを呼び出すか、またはそのクラス・ローダーで Class.forName(class_nameinitializeclass_loader) を呼び出すことができます。 アプリケーションで、クラス・ローダーのアプリケーション・プログラミング・インターフェース (API) を間違って使用している場合があります。 例えば、 クラス名が間違っている、クラスがそのクラス・ローダーの論理クラスパスにない、 または間違ったクラス・ローダーを使用している、などが考えられます。

この問題を 解決するには、クラスが存在するかどうか、およびアプリケーションが適切にクラス・ローダー API を使用しているかどうかを判別します。 コンテキスト・クラス・ローダーの論理クラスパスでクラスが表示されない のステップに従って、クラスがロードされているかどうかを判別します。 クラスがロードされていなかった場合は、アプリケーションの修正を試みてクラスがロードするかを確認します。 クラスが適切なアクセス権のある持つクラスパスにあり、別のファクトリ ー・クラスによってオーバーライドされていない場合は、クラスをロ ードするのに使用する API を調べます。

  1. トラブルシューティング > 「クラス・ローダー・ビューアー」 > module_name > 「検索」 をクリックして、クラス・ローダーの 「検索」ページにアクセスします。
  2. 「検索タイプ」「クラス/パッケージ」」を選択します。
  3. 「検索語」に、クラス名を入力します。
  4. OK」をクリックします。 「クラス名で検索 (Search by class name)」ページが表示され 、クラスをロードするすべてのクラス・ローダーがリストされます。
  5. ページを調べてそのクラスがリストに存在しているかどうか確認します。
  6. クラスがリストにあり、ClassNotFound 例外がスローされた場合は、.jar ファイルかクラスは正しいコンテキストにないか、現行コンテキストで間違った API 呼び出しが使用されています。
    リストにそのクラスがない場合は、「検索」ページに戻り、以下を 実行します。
    1. 例外を生成したクラス、すなわち、Class.forName を呼び出すクラスを検索します。
    2. どのクラス・ローダーがクラスをロードするかを確認します。
    3. クラス・ローダーがアクセス権を持っているかどうか、またはクラス・ローダーのクラスパスを実行することによって見つからないクラスをロードできるかどうかを判別します。
従属クラスが可視ではありません。
クラス・ローダー clsldr がクラス cls をロードする場合、 Java 仮想マシン (JVM) は、clsldr を呼び出して cls が従属するクラスをロードします。 従属クラスは、clsldr の論理クラスパス上で可視である必要があります。可視でない場合は、例外が発生します。 通常、この状態が発生するのは、ユーザーが WebSphere Application Server クラスを JVM に対して可視にするか、アプリケーション・クラスを JVM または WebSphere 拡張クラス・ローダーに対して可視にする場合です。 以下に例を示します。
  • クラス A はクラス B に従属しています。
  • クラス A は、WebSphere 拡張クラス・ローダーに見えています。
  • クラス B は、WAR モジュール・クラス・ローダーのローカル・クラスパス上では見えていますが、WebSphere 拡張クラス・ローダーのクラスパス上では見えていません。

JVM は、WebSphere 拡張クラス・ローダーを使用してクラス A をロードする場合、同じクラス・ローダーを使用してクラス B のロードを試み、結局、クラスが見つからないという例外を作成します。

以下の方法でこの問題を解決します。

  1. アプリケーション固有のクラスを適切なアプリケーションのクラス・ローダーに見えるようにします。
  2. 見つからなかったクラス (クラス B) を検索します。
  3. クラス B が適切な場所にある場合は、クラス・ローダー・ビューアーで、従属クラス (クラス A) をロードする クラスを検索 します。
  4. クラスがロードされ、 ClassNotFound 例外がスローされた場合.jarファイルまたはクラスが適切なコンテキストにないか、現行コンテキストで誤った API 呼び出しが使用されました。
    クラスが見つからなかった場合は、以下を実行します。
    1. 例外を生成したクラス、すなわち、Class.forName を呼び出すクラスを検索します。
    2. どのクラス・ローダーがクラスをロードするかを確認します。
    3. クラス・ローダーがアクセス権を持っているかどうか、またはクラス・ローダーのクラスパスを実行することによって見つからないクラスをロードできるかどうかを判別します。
  5. 呼び出し元のクラス (クラス B) が JVM または WebSphere 拡張クラス・ローダーに見えていることを確認します。

NoClassDefFoundException

no class definition found 例外は、以下の条件が存在する場合に発生し、次のアクシ ョンを実行することによって修正できます。

そのクラスが論理クラスパスにありません。
詳細は ClassNotFoundException を参照のこと。
クラスはロードができません。
クラスがロードできないのには、さまざまな理由があります。 理由には、従属クラスをロードできない、従属クラスのフォーマットが間違っているか、クラスのバージョン番号が違うといったものがあります。

UnsatisfiedLinkError

リンケージ・エラーは以下の条件が存在する場合に発生し、次のアクションを実行することによって修正できます。

ユーザーのアクションにより、エラーが発生しました。

いくつかのユーザー・アクションがリンケージ・エラーを発生させる場合があります。

ライブラリーの拡張名がそのプラットフォームに対して正しくありません。

[Windows]ライブラリーにはダイナミック・リンク・ライブラリー名があります library_name.dll

[AIX HP-UX Solaris]ライブラリーの名前は library_name.so または library_name.aです。

System.loadLibrary に正しくないパラメーターが渡されています。

[Windows] Name.dllという名前のダイナミック・リンク・ライブラリーをロードするには、 Name を loadLibrary 呼び出しに渡す必要があります。

[AIX HP-UX Solaris] libName.so または libName.aという名前のライブラリーをロードするために、 libName がロード・ライブラリーに渡されます。

ライブラリーが可視ではありません。
最良の方法は、JVM クラス・ローダーを使用して、ネイティブ・ライブラリーを検索またはロードすることです。 WebSphere Application Server は、始動時に Java ライブラリー・パス (java.library.path) を出力します。 JVM クラス・ローダーでライブラリーをロードする場合は、Java ライブラリー・パスに、ネイティブ・ライブラリー・ファイルを含むパスが存在することを確認します。 このパスが存在しない場合は、プラットフォーム固有のネイティブ・ライブラリー環境変数、 またはサーバー・プロセス定義の java.library.path システム・プロパティーにパスを追加します。

一般に、Java仮想マシンは、 System.loadLibrary( )を呼び出すクラスをロードするクラス・ローダー xxx 上で findLibrary( )を呼び出します。 xxx.findLibrary()が失敗した場合、Java仮想マシンは、JVMライブラリ・パスを検索するJVMクラス・ローダーを使用してライブラリを見つけようとします。 ライブラリーが見つからない場合は、Java 仮想マシンが UnsatisfiedLinkError 例外を作成します。

したがって、 WebSphere クラス・ローダーがネイティブ・ライブラリ myNativeLib を見つけることを意図している場合、そのライブラリは、 System.loadLibrary(myNativeLib を呼び出すクラスをロードするクラス・ローダーの nativelibpath 上で可視でなければなりません。)この方法は、次のような場合に必要または望ましい:

  • 共有ライブラリーの構成には、「ネイティブ・ライブラリー・パス (Native library path)」があります。 共有ライブラリーは、アプリケーション固有ライブラリーのバージョン管理が可能なため、共有ライブラリー・コードが使用するすべてのネイティブ・ライブラリーのパスを、共有ライブラリー構成で指定することを検討します。

正しい WebSphere クラス・ローダーが、System.loadLibrary() を呼び出すクラスをロードすること、およびネイティブ・ライブラリーが「ネイティブ・ライブラリー・パス (Native library path)」設定で可視であることを確認します。

[AIX HP-UX Solaris]
System.mapLibraryName は間違ったライブラリー・ファイルを戻します。
共有ライブラリーをロードする場合、JVM は mapLibraryName(libName) を呼び出し、 libName をプラットフォーム固有の名前に変換します。 AIX®、 HP-UX、またはSolarisオペレーティング・システムでは、このコールは間違った拡張子を持つファイル名を返すかもしれない(例えば、 libName.a ではなく libName.so )。 この問題をデバッグするには、System.mapLibraryName() を呼び出すプログラムを作成し、それが正しいファイル名を戻すことを確認します。
ネイティブ・ライブラリーはすでにロードされている。
この状態は、以下のエラーのうちのいずれかの結果で起こることがあります。
ユーザー・エラー
System.loadLibrary に対する複数の呼び出しをチェックし、余分な呼び出しを除去します。
アプリケーション再始動時のエラー
JVM には制限があり、ネイティブ・ライブラリーをロードできるのは、1 度に 1 つのクラス・ローダーのみです。 停止済みアプリケーションからガーベッジ・コレクターがクラス・ローダーをクリーンアップする前に アプリケーションを再始動すると、エラーが発生します。 ネイティブ・ライブラリーをロードするクラスを移動する場合には、 そのネイティブ・ライブラリーに依存するすべてのクラスとそれらの依存関係も移動する必要があります。

このエラー状態を訂正するには、ネイティブ・ライブラリーのロードを、再ロードを行わないクラス・ローダーに移動します。以下の手順で移動してください。

  1. ネイティブ・ライブラリーをロードする、またはネイティブ・メソッドを保持するすべてのアプリケーション・クラスを、位置指定します。
  2. ステップ 1 のクラスの従属クラス (ロギング・パッケージなど) を識別します。
  3. サーバーに関連付けられた共有ライブラリーを作成するか、または個別の共有ライブラリーを作成します。
  4. ステップ 1 および 2 でクラス用にロードされた JAR ファイルを、アプリケーションから、ステップ 3 で作成した共有ライブラリーへ移動します。
  5. 変更を保存します。
  6. アプリケーションを再デプロイし、シナリオを再実行します。

サーバーを有効範囲としたライブラリー内のクラスは、 各サーバーのライフサイクルで一回ロードされます。 これにより、アプリケーションのライフサイクルにかかわらず、アプリケーションで必要なネイティブ・ライブラリーが Java 仮想マシンごとに必ず 1 回ロードされることになります。

従属したネイティブ・ライブラリー使用されました。
従属したネイティブ・ライブラリーが JVM クラス・ローダーによって検索またはロードされる必要があります。 つまり、ネイティブ・ライブラリー NL が別のネイティブ・ライブ ラリー DNL に従属している場合、JVM クラス・ローダーは Java ライブラリー・パス上の DNL を検索する必要があります。 これは、NL をロードする場合に JVM がネイティブ・コードを実行するためです。DNL への従属がある場合、JVM ネイティブ・コードは JVM クラス・ローダーを呼び出すだけで従属を解決することができます。 WebSphere クラス・ローダーが従属したネイティブ・ライブラリーをロードできません。

Java ライブラリー・パス (LIBPATH) を定義するプラットフォーム固有の環境変数を変更して、 未解決のネイティブ・ライブラリーを含むパスを組み込みます。