Java Lambda 関数からの「ClassNotFoundException」エラーと「NoSuchMethodError」エラーのトラブルシューティング方法を教えてください。
最終更新日: 2022 年 2 月 3 日
AWS Lambda 関数を呼び出そうとすると、「ClassNotFoundException」エラーまたは「NoSuchMethodError」エラーが発生します。これらのエラーを解決するにはどうすればよいですか。
簡単な説明
ClassNotFoundException エラーは、Java ランタイムが完全修飾名でクラスをロードしても、クラスを検索しない場合に発生します。
注: Java の完全修飾クラス名には、クラスのデプロイパッケージとクラス名が含まれます。
参照する依存関係バージョンがパッケージ化されたバージョンと異なる場合、NoSuchMethodError エラーが生成します。
Java Lambda 関数のデプロイパッケージの構造の詳細については、「.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする」を参照してください。
解決方法
注: AWS Command Line Interface (AWS CLI) コマンドの実行中にエラーが発生した場合は、AWS CLI の最新バージョンを使用していることを確認してください。
Lambda 関数のデプロイパッケージをダウンロードする
Lambda 関数のデプロイパッケージのファイル構造を表示するには、下記のいずれかを実行します。
zipinfo コマンドを実行して関数のデプロイパッケージをダウンロードするには
次の zipinfo コマンドを実行します。
重要: my-deployment-package.zip をデプロイパッケージのファイル名に置き換えます。次のコマンドは、Linux、UNIX、および macOS オペレーティングシステムでのみ有効です。
$ zipinfo my-deployment-package.zip
Lambda get-function AWS CLI コマンドを実行して関数のデプロイパッケージをダウンロードするには
次の get-function コマンドを実行します。
重要: my-function を Lambda 関数の名前に置き換えてください。
aws lambda get-function \
--function-name my-function
コマンド出力は、ファイルのダウンロードに使用できる署名付き URL を提供します。詳細については、「Lambda 関数の取得」を参照してください。
Lambda コンソールから関数のデプロイパッケージをダウンロードするには
1. Lambda コンソールの関数ページで関数を選択します。
2. [Actions] (アクション) を選択します。
3. [Export function] (関数のエクスポート) を選択します。
4. [Export your function] (関数のエクスポート) ダイアログボックスで、[Download deployment package] (デプロイパッケージのダウンロード) を選択します。
関数ハンドラーメソッド名を確認
詳細については、「Java の AWS Lambda 関数ハンドラー」を参照してください。
CI/CD パイプラインの問題を確認する
継続的インテグレーションと継続的デリバリー (CI/CD) パイプラインを使用して関数をパッケージ化してデプロイする場合は、次を検証します。
- 必要な依存関係はすべて、関数をパッケージ化する時にバンドルされています。
- 参照される依存関係のバージョンはすべて正しいです。
- 必要な Amazon Simple Storage Service (Amazon S3) のバケット URL が存在し、ファイルの最新バージョンを指しています。
注: Amazon S3 バケット URL は、Amazon S3 バケットソースを使用していて、バケットのバージョニングが有効になっている場合にのみ必要です。 - ハンドラー設定の変更をデプロイする前に、コードの変更がデプロイされました。
注: Lambda には、1 つのアトミック変更でコードと設定を更新するメカニズムはありません。
クラスファイルの問題を確認する
ClassNotFoundException エラーで指定されたクラスについて、次を検証します。
- デプロイパッケージに含まれています。
注: クラスが見つからない場合は、デプロイパッケージの作成時にバンドルされていない可能性があります。 - バンドルされたクラス名は、関数のハンドラー値と同じです。
- これは、/lib またはルートディレクトリにあります。
- Lambda レイヤーとして参照されている場合、その内容は java/lib 以外のディレクトリに抽出されていません。
- 関数にパッケージ化されたクラスと同じバージョンです。クラスが同じバージョンでない場合、パッケージ化したものと異なるバージョンがローカルマシンにあるかを確認します。
JAR ファイルの問題を確認する
関数がローカルマシン、または AWS SAM (AWS Serverless Application Model) アプリケーションで正常に実行されるかどうかを確認します。Lambda から呼び出された時にのみ関数が失敗する場合は、参照される依存関係 (JAR ファイル) に問題がある可能性があります。
ヒント: Eclipse 統合開発環境 (IDE) を使用して Java Lambda 関数を構築することを検討してください。Eclipse で使用可能なプラグインを使ってプロジェクトを作成すると、自動的にプロジェクトが適切なビルド用に設定されます。詳細については、「AWS Toolkit for Eclipse で Lambda を使用する」を参照してください。
ローカルディレクトリに存在し、Java CLASSPATH 環境変数で指定されている JAR ファイルについて、次を検証します。
- ファイルは関数のデプロイパッケージに含まれています。
注: 参照されている JAR ファイルが見つからない場合は、デプロイパッケージの作成時にバンドルされていない可能性があります。 - ファイルバージョンは、デプロイパッケージ内のファイルと同じです。
ファイルが見つからないか、バージョンが正しくない場合は、すべての依存関係 (JAR ファイル) を /lib またはルートディレクトリにコピーします。正しいバージョンを参照していることを確認してください。次に、圧縮したコンテンツをアップロードします。
注: Apache Maven や Gradle などのビルドツールを使用している場合は、デプロイアーティファクトのビルド時に必要なプラグインを使用してください。たとえば、Apache Maven Shade プラグインなどです。
権限問題を確認する
Lambda では、zip パッケージファイルにグローバルな読み取り権限が付与される必要があります。詳細については、「Lambda デプロイパッケージをアップロードするときに「権限が拒否されました」または「モジュールをインポートできません」というエラーを解決するには、どうすればよいですか?」を参照してください。
重要: 問題を特定して修正したら、Lambda 関数を手動でバンドルしてアップロードしデプロイする必要があります。次に、引き続きエラーが発生するかどうかを確認します。