如何解决 Java Lambda 函数中的“ClassNotFoundException”和“NoSuchMethodError”错误?

上次更新日期:2022 年 2 月 3 日

当我尝试调用我的 Java AWS Lambda 函数时,我收到了“ClassNotFoundException”或“NoSuchMethodError”错误。如何解决这些错误?

简短描述

Java 运行时通过其完全限定的名称加载类但找不到该类时,会发生 ClassNotFoundException 错误。

注意: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 控制台的 Functions(函数)页面上,选择您的函数。

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 存储桶源且启用存储桶版本控制时,才需要 Amazon Simple Storage Service (Amazon S3) 存储桶 URL。
  • 代码更改是在部署处理程序配置更改之前部署的。
    注意:Lambda 没有在一个原子更改中更新代码和配置的机制。

检查是否存在任何类文件问题

针对 ClassNotFoundException 错误中指定的类验证以下内容:

  • 它包含在部署程序包中。
    注意:如果找不到该类,则在您创建部署程序包时,该类可能尚未捆绑。
  • 其捆绑的类名称与函数的处理程序值相同。
  • 它位于 /lib 或根目录中。
  • 如果将其引用为 Lambda 层,则其内容不会提取到除 java/lib 以外的目录中。
  • 它与函数打包的类的版本相同。如果类不是同一个版本,则请检查本地计算机的版本是否与您打包的版本不同。

检查是否存在任何 JAR 文件问题

确认您的函数是按预期在本地计算机上运行,还是从 AWS 无服务器应用程序模型 (AWS SAM) 应用程序执行。如果函数仅在从 Lambda 调用时失败,则引用的依赖关系(JAR 文件)可能会出现问题。

提示:考虑使用 Eclipse 集成开发环境 (IDE) 来构建 Java Lambda 函数。使用 Eclipse 中可用的插件创建项目会自动为项目配置正确的版本。有关更多信息,请参阅将 Lambda 与 AWS Toolkit for Eclipse 配合使用

对位于本地目录中并在 Java CLASSPATH 环境变量中指定的 JAR 文件验证以下内容:

  • 这些文件包含在函数的部署程序包中。
    注意:如果找不到引用的 JAR 文件,则在您创建部署程序包时,这些文件可能尚未绑定。
  • 文件版本与部署程序包中的文件版本相同。

如果文件丢失或其版本不正确,请将所有依赖关系(JAR 文件)复制到 /lib 或根目录。请确保引用正确的版本。然后,上载压缩的内容。

注意: 如果您使用的是 Apache Maven 或 Gradle 等构建工具,请确保在构建部署构件时使用所需的插件。例如,Apache Maven Shade 插件

检查是否存在任何权限问题

Lambda 要求 zip 程序包文件具有全局读取权限。有关更多信息,请参阅如何解决我在上载 Lambda 部署程序包时遇到的 Lambda 错误“permission denied”或“unable to import module”?

重要提示:确定并修复问题后,您必须手动捆绑并上载您的 Lambda 函数才能进行部署。然后,检查是否仍会收到错误。