如何使用 Java Lambda 函数排查“ClassNotFoundException”错误?

上次更新时间:2020 年 2 月 28 日

当我运行使用 Java 编写的 AWS Lambda 函数时,我收到“ClassNotFoundException”或“NoSuchMethodError”错误。如何处理这些错误?

简短描述

当试图通过完全限定名称(带有类名的包)加载类时,Java 运行时会引发“ClassNotFoundException”错误,无法找到类。当引用的依赖关系版本与打包版本不同时,运行时会引发“NoSuchMethodError”错误。

有关 Java 函数部署程序包结构的信息,请参见为 Java 函数创建 ZIP 部署程序包

解决方法

查看 Java Lambda 函数的部署程序包的结构和内容,以确定发生错误的原因。最佳做法是使用 zipinfo 查看构建系统的输出 Java 文件。或者,您可以通过执行以下任一操作来下载程序包:

  • AWS 命令行界面 (AWS CLI) 运行 Lambda get-function 命令。命令输出显示可用于下载文件的预签名 URL。有关更多信息,请参阅检索 Lambda 函数
    注意:如果使用此选项,则还应检查输出中函数处理程序的值配置。您需要此值来执行下一步。
  • 在 Lambda 控制台的函数页面上,选择您的函数。选择操作,然后选择导出函数。在导出您的函数对话框中,选择下载部署程序包

查找是否存在以下任何问题。确定并修复问题后,手动捆绑并上传 Lambda 函数。然后,检查是否仍会收到错误。

确认函数处理程序方法名

通过执行以下操作之一检查 Lambda 函数处理程序的名称:

有关更多信息,请参阅采用 Java 编写的 AWS Lambda 函数处理程序

查看部署程序包结构

运行以下命令以查看 Lambda 函数部署程序包的文件结构

注意:此命令仅对 Linux/Unix/macOS 系统有效。将 my-deployment-package.zip 替换为部署程序包的文件名。

$ zipinfo my-deployment-package.zip

使用 CI/CD 管道时检查是否存在问题

如果您正在使用持续集成和持续交付 (CI/CD) 管道来打包和部署您的函数,请验证以下内容:

检查是否存在类文件问题

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

  • 它包含在部署程序包中。如果找不到该类,则在您创建部署程序包时,该类可能尚未捆绑。
  • 其捆绑的类名称与函数的处理程序值相同。例如,如果函数处理程序值为“com.amazonaws.lambda.demo.LambdaFunctionHandler”,则 Lambda 要求函数目录“/com/amazonaws/demo/”中的类名为“LambdaFunctionHandler.class”。有关更多信息,请参阅采用 Java 编写的 AWS Lambda 函数处理程序
  • 它位于 /lib 或根目录中。
  • 其位置在 Java CLASSPATH 环境变量中指定。
  • 如果将其引用为 Lambda 层,则其内容不会提取到除 java/lib 以外的目录中。
  • 它与函数打包的类的版本相同。否则,请检查您的本地计算机的版本是否与您打包的版本不同。

有关打包 Java 函数的更多信息,请参阅采用 Java 编写的 AWS Lambda 部署程序包

检查是否存在 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 插件)来捆绑所有必需的依赖关系。

有关打包 Java 函数的更多信息,请参阅采用 Java 编写的 AWS Lambda 部署程序包

检查权限问题

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