AWS Lambda 関数を呼び出そうとすると、「ClassNotFoundException」エラーまたは「NoSuchMethodError」エラーが発生します。これらのエラーを解決するにはどうすればよいですか?
簡単な説明
ClassNotFoundException エラーは、Java ランタイムが完全修飾名でクラスをロードしても、クラスを検索しない場合に発生します。
注: Java の完全修飾クラス名には、クラスのデプロイパッケージとクラス名が含まれます。
NoSuchMethodError エラーは、参照する依存関係バージョンがパッケージバージョンと異なる場合に発生します。
Java Lambda 関数デプロイパッケージ構造の詳細については、「Deploy Java Lambda functions with .zip or JAR file archives」を参照してください。
解決策
注: AWS コマンドラインインターフェイス (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. [アクション] を選択します。
3. [関数のエクスポート] を選択します。
4. [関数のエクスポート] ダイアログボックスで、[デプロイパッケージのダウンロード] を選択します。
関数ハンドラーメソッド名を確認する
詳細については、「AWS Lambda function handler in Java」を参照してください。
CI/CD パイプラインの問題を確認する
継続的インテグレーションと継続的デリバリー (CI/CD) パイプラインを使用して関数をパッケージ化してデプロイする場合は、以下について検証します。
クラスファイルの問題を確認する
ClassNotFoundException エラーで指定されたクラスについて、以下を検証します。
- デプロイパッケージに含まれている。
注: クラスが見つからない場合は、デプロイパッケージを作成した際にバンドルされていない可能性があります。
- バンドルされたクラス名が、関数のハンドラー値と同じである。
- /lib またはルートディレクトリに置かれている。
- Lambda レイヤーとして参照される場合、その内容が java/lib 以外のディレクトリに抽出されていない。
- 関数にパッケージされているクラスと同じバージョンである。クラスが同じバージョンでない場合、パッケージしたものと異なるバージョンがローカルマシンにあるかを確認します。
JAR ファイルの問題を確認する
関数がローカルマシン、または AWS サーバーレスアプリケーションモデル (AWS SAM)で正常に実行されるかどうかを確認します。Lambda から呼び出されたときにのみ関数が失敗する場合は、参照される依存関係 (JAR ファイル) に問題がある可能性があります。
ヒント: Eclipse 統合開発環境 (IDE) を使用して Java Lambda 関数を構築することを検討してください。Eclipse で利用可能なプラグインを使ってプロジェクトを作成すると、自動的にプロジェクトが適切なビルド用に設定されます。詳細については、「Using Lambda with the AWS Toolkit for Eclipse」を参照してください。
ローカルディレクトリに存在し、Java CLASSPATH 環境変数で指定されている JAR ファイルについて、以下を検証します。
- ファイルが関数のデプロイパッケージに含まれている。
注: 参照されている JAR ファイルが見つからない場合は、デプロイパッケージの作成時にバンドルされていない可能性があります。
- ファイルバージョンが、デプロイパッケージ内のファイルと同じである。
ファイルが見つからない場合や、バージョンが正しくない場合は、すべての依存関係 (JAR ファイル) を /lib またはルートディレクトリにコピーします。正しいバージョンを参照していることを確認してください。その後に、圧縮したコンテンツをアップロードします。
注: Apache Maven や Gradle などのビルドツールを使用している場合は、デプロイアーティファクトのビルド時に必要なプラグインを使用してください。例えば、Apache Maven Shade Plugin などです。
権限の問題を確認する
Lambda では、zip パッケージファイルにグローバルな読み取り権限が付与される必要があります。詳細については、「Lambda デプロイパッケージをアップロードする際に表示される「アクセス許可が拒否されました」と「unable to import module」というエラーを解決するにはどうすればよいですか?」を参照してください。
重要: 問題を特定して修正したら、Lambda 関数を手動でバンドルしてアップロードしてデプロイする必要があります。次に、引き続きエラーが発生するかどうかを確認します。
関連情報
AWS Lambda function errors in Java
Instrumenting Java code in AWS Lambda
Including library dependencies in a Layer
Best practices for working with AWS Lambda functions