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 関数を手動でバンドルしてアップロードしデプロイする必要があります。次に、引き続きエラーが発生するかどうかを確認します。