アプリケーションの開発時、あるいはインストール済みアプリケーションの開始時に発生するクラス・ロード・エラーの種類を特定してください。
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」コンソール・ページを使用します。
- 「トラブルシューティング」>「Class Loader Viewer」> module_name >
「検索」をクリックして、検索ページにアクセスします。
- 「検索タイプ」に「クラス/パッケージ」を選択します。
- 「検索項目」に、
2 つのクラス・ローダーによってロードされるクラスの名前を入力します。
- 「OK」をクリックします。「Search by Class Name」ページが表示され
、クラスをロードするすべてのクラス・ローダーがリストされます。
複数のクラス・ローダーがリストされた場合は、ターゲット・クラスが複数のクラス・ローダーによってロードされています。
ソース・オブジェクトはターゲット・クラスのインスタンスであるため、
ソース・オブジェクト・クラスをロードするクラス・ローダーが、ターゲット・クラスをロードするクラス・ローダーと異なります。
- クラス・ローダー・ビ
ューアー・ページに戻り、クラスパスを調べて、2 つの異なるクラス・ローダーがクラスをロードする理由を判別します。
- 該当するクラス・ローダーのみにクラスが見えるように、コードを修正します。
- アプリケーションが、
絞り込み操作を実行しないか、または実行が不適切です。
- クラス・キャスト例外は、アプリケーションがリモート・エンタープライズ Bean (EJB) オブジェクトを解決しているときに、
アプリケーション・コードが必要な絞り込み操作を実行しないために起こります。アプリケーションは、リモート・オブジェクトを検索した後で絞り込み操作を実行する必要があります。
アプリケーションを調査し、アプリケーションがリモート・オブジェクトを検索するかどうかを判別し、検索する場合には、検索の結果を絞り込みメソッドに送信します。
絞り込みメソッドは、EJB 2.0 プログラミング・モデルに従って呼び出される必要があります。特に、絞り込みメソッドに送信されるターゲット・クラスは、EJB の正確な最派生インターフェースでなければなりません。これは、
WebSphere Application Server ランタイム環境でのクラス・キャスト例外の
原因にもなります。アプリケーションを調査し、絞り込みメソッドに送信されるターゲット・クラスが、
正確な EJB タイプではなく、指定された EJB のスーパー・インターフェースとなっていないか判別します。そうである場合は、正確な EJB インターフェースで絞り込みを呼び出すようにアプリケーションを修正します。
最後に、絞り込み操作中に
クラス・キャスト例外が発生する場合は、絞り込みメソッドが、ローカル・エンタープライズ Bean ではなく、
リモート EJB の検索結果に適用されていることを確認します。絞り込みは、ローカル検索には使用されません。
アプリケーションまたはモジュールのデプロイメント記述子を検査して、絞り込み検索対象のオブジェクトがローカル・オブジェクトでないことを確認します。
ClassNotFoundException
class not found exception は、以下の条件が存在する場合に発生し、次のアクションを実行するこ
とによって修正できます。
- クラスが
コンテキスト・クラス・ローダーの論理クラスパスで可視ではありません。
- 見つからないクラスは、現在のスレッドに関連付けられている
クラス・ローダーの論理クラスパスに存在しません。
論理クラスパスは、ロード操作がクラス・ローダーで呼び出されたときに検索されるすべてのクラスパスの累積です。
この問題を修正するには、「検索」ページを使用してクラス名および
Java archive (JAR) 名で検索します。
- 「トラブルシューティング」>「Class Loader Viewer」>「module_name」>「検索」をクリックして、クラス・ローダー検索ページにアクセスします。
- 「検索タイプ」に「クラス/パッケージ」を選択します。
- 「検索項目」に、
見つからないクラス名を入力します。
- 「OK」をクリックします。「Search by Class Name」ページが表示され
、クラスをロードするすべてのクラス・ローダーがリストされます。
- ページを調べてそのクラスがリストに存在しているかどうか確認します。
- リストにそのクラスがない場合は、「検索」ページに戻ります。「検索項目」に、クラスの .jar ファイル名を入力し、「検索タイプ」で「JAR/ディレクトリー」を選択します。
- 「OK」をクリックします。「Search by Path」ページが表示され、JAR
ファイルを格納しているすべてのディレクトリーがリストされます。
JAR ファイルがリストにない場合、そのクラスは論理クラスパスにないか、読み取り不能か、代替クラスがすでにロードされている場合があります。
クラスを、ロードできるロケーションに移動します。
- アプリケーションが
クラス・ローダー API を間違って使用します。
- アプリケーションは、クラス・ローダーのインスタンスを取得し、
そのクラス・ローダーの loadClass メソッドを呼び出すか、またはそのクラス・ローダーで Class.forName(class_name、initialize、class_loader) を呼び出すことができます。アプリケーションで、クラス・ローダーのアプリケーション・プログラミング・インターフェース (API) を間違って使用している場合があります。例えば、
クラス名が間違っている、クラスがそのクラス・ローダーの論理クラスパスにない、
または間違ったクラス・ローダーを使用している、などが考えられます。
この問題を
解決するには、クラスが存在するかどうか、およびアプリケーションが適切にクラス・ローダー API を使用しているかどうかを判別します。クラスがロードされているかどうかを判別するには、
クラスがコンテキスト・クラス・ローダーの論理クラスパスで可視ではありませんのステップを実行します。
クラスがロードされていなかった場合は、アプリケーションの修正を試みてクラスがロードするかを確認します。
クラスが適切なアクセス権のある持つクラスパスにあり、別のファクトリ
ー・クラスによってオーバーライドされていない場合は、クラスをロ
ードするのに使用する API を調べます。
- 「トラブルシューティング」>「Class Loader Viewer」>「module_name」>「検索」をクリックして、クラス・ローダー検索ページにアクセスします。
- 「検索タイプ」に「クラス/パッケージ」を選択します。
- 「検索項目」に、
クラス名を入力します。
- 「OK」をクリックします。「Search by Class Name」ページが表示され
、クラスをロードするすべてのクラス・ローダーがリストされます。
- ページを調べてそのクラスがリストに存在しているかどうか確認します。
- クラスがリストにあり、ClassNotFound 例外がスローされた場合は、.jar ファイルかクラスは正しいコンテキストにないか、現行コンテキストで間違った API 呼び出しが使用されています。
リストにそのクラスがない場合は、「検索」ページに戻り、以下を
実行します。
- 例外を生成したクラス、すなわち、Class.forName を呼び出すクラスを検索します。
- どのクラス・ローダーがクラスをロードするかを確認します。
- クラス・ローダーがアクセス権を持っているかどうか、またはクラス・ローダーのクラスパスを実行することによって見つからないクラスをロードできるかどうかを判別します。
- 従属クラスが可視ではありません。
- クラス・ローダー clsldr がクラス cls をロードする場合、
Java 仮想マシン (JVM) は、clsldr を呼び出して cls が従属するクラスをロードします。
従属クラスは、clsldr の論理クラスパス上で可視である必要があります。可視でない場合は、例外が発生します。
このような状態は、一般的に、ユーザーが WebSphere Application Server クラスを JVM に
見えるようにするか、またはアプリケーション・クラスを JVM または WebSphere の拡張クラス・ローダーに
見えるようにした場合に発生します。以下に例を示します。
- クラス A はクラス B に従属しています。
- クラス A は、WebSphere 拡張クラス・ローダーに見えています。
- クラス B は、WAR モジュール・クラス・ローダーのローカル・クラスパス上では見えていますが、WebSphere 拡張クラス・ローダーのクラスパス上では見えていません。
JVM は、WebSphere 拡張クラス・ローダーを使用してクラス A をロードする場合、同じクラス・ローダーを使用してクラス B のロードを試み、結局、クラスが見つからないという例外を作成します。
以下の方法でこの問題を解決します。
- アプリケーション固有のクラスを適切なアプリケーションのクラス・ローダーに見えるようにします。
- 見つからなかったクラス (クラス B) を検索します。
- クラス B が適切なロケーションにある場合、クラス・ロード・ビュー
アーで、従属クラス (クラ
ス A) をロードするクラスの検索を行います。
- クラスがロードされており、ClassNotFound 例外がスローされていた
場合、.jar ファイルまたはクラスは適切なコンテキストにないか現行コンテキストで間違った API 呼び出しが使用されています。
クラスが見つからなかった場合は、以下を実行します。
- 例外を生成したクラス、すなわち、Class.forName を呼び出すクラスを検索します。
- どのクラス・ローダーがクラスをロードするかを確認します。
- クラス・ローダーがアクセス権を持っているかどうか、またはクラス・ローダーのクラスパスを実行することによって見つからないクラスをロードできるかどうかを判別します。
- 呼び出し元のクラス (クラス B) が JVM または WebSphere 拡張クラス・ローダーに見えていることを確認します。
NoClassDefFoundException
no class
definition found 例外は、以下の条件が存在する場合に発生し、次のアクシ
ョンを実行することによって修正できます。
- そのクラスが論理クラスパスにありません。
- 詳しくは、ClassNotFoundExceptionを参照してください。
- クラスはロードができません。
- クラスがロードできないのには、さまざまな理由があります。理由には、従属クラスをロードできない、従属クラスのフォーマットが間違っているか、クラスのバージョン番号が違うといったものがあります。
UnsatisfiedLinkError
リンケージ・エラーは以下の条件が存在する場合に発生し、次のアクションを実行することによって修正できます。
- ユーザーのアクションにより、エラーが発生しました。
いくつかのユーザー・アクションがリンケージ・エラーを発生させる場合があります。
- ライブラリーの拡張名がそのプラットフォームに対して正しくありません。
- System.loadLibrary に正しくないパラメーターが渡されています。
- ライブラリーが可視ではありません。
- 最良の方法は、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 で可視である必要があります。このような方法が、必要または適しているのは、次のような状態です。
- データ・ソース・プロバイダーのネイティブ・ライブラリーは、WebSphere 拡張クラス・ローダーの nativelibpath で可視である必要があります。この場合は、
ネイティブ・ライブラリーを含むパスを、データ・ソース・プロバイダー構成の Native Lib
Path 設定に追加します。
- 共用ライブラリーの構成に、Native Library Path があります。共用ライブラリーは、アプリケーション固有ライブラリーのバージョン管理が可能なため、共用ライブラリー・コードが使用するすべてのネイティブ・ライブラリーのパスを、共用ライブラリー構成で指定することを検討します。
正しい WebSphere クラス・ローダーが、System.loadLibrary() を呼び出すクラスをロードすること、およびネイティブ・ライブラリーが Native Library Path 設定で可視であることを確認します。
- ネイティブ・ライブラリーがすでにロードされています。
- この状態は、以下のエラーのうちのいずれかの結果で起こることがあります。
- ユーザー・エラー
- System.loadLibrary に対する複数の呼び出しをチェックし、余分な呼び出しを除去します。
- アプリケーション再始動時のエラー
- サーバーを有効範囲とした共有ライブラリー中のクラスの静的初期化において、System.loadLibrary() を呼び出します。
- アプリケーションのソース・コードから、
System.loadLibrary(MyNativeLib) 呼び出しのすべてのインスタンス
を除去します。
- 静的ブロック内に、System.loadLibrary(MyNativeLib) を呼び出す LibLoader という名前の新しいクラスを作成します。
以下に例を示します。
public class LibLoader {
static {System.loadLibrary(MyNativeLib);}
public LibLoader();
}
- サーバーを有効範囲とした共有ライブラリーを作成します。
- 共用ライブラリーの作成を行い、
その有効範囲を「server」に設定してライブラリー名を MySharedLib とします。
- 共有ライブラリーの
設定ページに進みます。
- 「クラスパス」をクラスの LibLoader を含むパスに設定します。
- 「ネイティブ・ライブラリー・パス」をネイティブ・ライブラリー MyNativeLib を含むパスに設定します。
- アプリケーションをホストしているサーバー上で
クラス・ローダーを作成します。
- MySharedLib を新しいサーバー・クラス・ローダーに関連付けます。共用ライブラリーとサーバーの関連付け
のステップ 2 を参照してください。
- 変更を保管します。
- アプリケーションを再デプロイし、シナリオを再実行します。
サーバーを有効範囲としたライブラリー内のクラスは、各サーバーのライフ・サイクルで一度ロードされ、アプリケーションのライフ・サイクルにかかわらず、アプリケーションで必要なネイティブ・ライブラリーが各 Java 仮想マシンについて一度ロードされることを確認します。
- 従属したネイティブ・ライブラリー使用されました。
- 従属したネイティブ・ライブラリーが JVM クラス・ローダーによって検索またはロードされる必要があります。
つまり、ネイティブ・ライブラリー NL が別のネイティブ・ライブ
ラリー DNL に従属している場合、JVM クラス・ローダーは Java ライブラリー・パス上の DNL を検索する必要があります。これは、NL をロードする場合に JVM がネイティブ・コードを実行するためです。DNL への従属がある場合、JVM ネイティブ・コードは JVM クラス・ローダーを呼び出すだけで従属を解決することができます。
WebSphere クラス・ローダーが従属したネイティブ・ライブラリーをロードできません。
Java ライブラリー・パス (LIBPATH) を定義するプラットフォーム固有の環境変数を変更して、
未解決のネイティブ・ライブラリーを含むパスを組み込みます。