简体   繁体   English

带有Java的AWS Lambda抛出由ClassNotFoundException引起的NoClassDefFoundError,该异常未在本地抛出

[英]AWS Lambda with java throwing NoClassDefFoundError caused by ClassNotFoundException which isn't thrown locally

I've recently started playing around with AWS Lambda with Java. 我最近开始使用带有Java的AWS Lambda。

It has been going well, until I started using Dagger 2 for injection. 一直很好,直到我开始使用Dagger 2进行注射。

Now Lambda throws the following error: 现在,Lambda引发以下错误:

{
  "errorMessage": "dagger/internal/Preconditions",
  "errorType": "java.lang.NoClassDefFoundError",
  "stackTrace": [
    "com.company.server.user.SignUpActionAws.handler(SignUpActionAws.java:27)",
    "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
    "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
    "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
    "java.lang.reflect.Method.invoke(Method.java:498)"
  ],
  "cause": {
    "errorMessage": "dagger.internal.Preconditions",
    "errorType": "java.lang.ClassNotFoundException",
    "stackTrace": [
      "java.net.URLClassLoader.findClass(URLClassLoader.java:381)",
      "java.lang.ClassLoader.loadClass(ClassLoader.java:424)",
      "java.lang.ClassLoader.loadClass(ClassLoader.java:357)",
      "com.company.server.user.SignUpActionAws.handler(SignUpActionAws.java:27)",
      "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
      "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)",
      "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
      "java.lang.reflect.Method.invoke(Method.java:498)"
    ]
  }
}

However, this does not occur when running java -jar myjar.jar locally. 但是,在本地运行java -jar myjar.jar时不会发生这种情况。 I've also checked that the class is in there using jar tvf myjar.jar . 我还使用jar tvf myjar.jar检查了该类是否在其中。

I build using Bazel. 我使用Bazel构建。

Other questions I've checked have suggested that it might be due to a dependency not being available, however, the contents of the class has no dependencies. 我检查过的其他问题表明,这可能是由于不存在依赖项,但是,类的内容没有依赖项。

Taken from the Dagger repo : 摘自Dagger仓库

/*
 * Copyright (C) 2016 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dagger.internal;

/**
 * An adaptation of Guava's {@code com.google.common.base.Preconditions} that is specially tailored
 * to support checks applied in Dagger's generated code.
 */
public final class Preconditions {
  /**
   * Ensures that an object reference passed as a parameter to the calling method is not null.
   *
   * @param reference an object reference
   * @return the non-null reference that was validated
   * @throws NullPointerException if {@code reference} is null
   */
  public static <T> T checkNotNull(T reference) {
    if (reference == null) {
      throw new NullPointerException();
    }
    return reference;
  }

  /**
   * Ensures that an object reference passed as a parameter to the calling method is not null.
   *
   * @param reference an object reference
   * @param errorMessage the exception message to use if the check fails
   * @return the non-null reference that was validated
   * @throws NullPointerException if {@code reference} is null
   */
  public static <T> T checkNotNull(T reference, String errorMessage) {
    if (reference == null) {
      throw new NullPointerException(errorMessage);
    }
    return reference;
  }

  private Preconditions() {}
}

What might be causing the issue on AWS that doesn't occur on my local environment when running a self-contained jar? 运行自包含jar时,可能是什么导致AWS上在本地环境中没有发生的问题?

Thanks in advance 提前致谢

Edit 1: Here is the minimal BUILD file: 编辑1:这是最小的BUILD文件:

java_binary(
  name = "bin",
  srcs = glob(["Action.java"]),
  main_class = "com.company.Action",
  deps = [
    "//external:aws-lambda",
    "//external:dagger",
  ]
)

Here is the WORKSPACE file: 这是WORKSPACE文件:

bind(name = "aws-lambda", actual = "@com_amazonaws_aws_lambda_java_core//jar")
maven_jar(
  name = "com_amazonaws_aws_lambda_java_core",
  artifact = "com.amazonaws:aws-lambda-java-core:1.1.0"
)
bind(name = "dagger", actual = "@com_google_dagger//jar")
maven_jar(
  name = "com_google_dagger",
  artifact = "com.google.dagger:dagger:2.5",
)

Here is Action.java (note, I use Preconditions directly to make it the minimal implementation, in my actual code it fails when trying to build a component): 这是Action.java(请注意,我直接使用Preconditions使其成为最小的实现,在我的实际代码中,尝试构建组件时失败):

package com.company;

import com.amazonaws.services.lambda.runtime.Context;

public class Action {
  public static void main(String[] s) {
    Action.handler(null, null);
  }

  public static String handler(String request, Context context) {
    dagger.internal.Preconditions.checkNotNull(new Object(), "Test");
    return null;
  }
}

If you run bazel build //src/main/com/company:bin_deploy.jar and upload it to an AWS Lambda function, it should fail. 如果您运行bazel build //src/main/com/company:bin_deploy.jar并将其上传到AWS Lambda函数,它将失败。 If you locally run bazel run //src/main/com/company:bin or java -jar bazel-bin/src/main/com/company/bin_deploy.jar it will work fine. 如果您在本地运行bazel run //src/main/com/company:binjava -jar bazel-bin/src/main/com/company/bin_deploy.jar ,它将正常运行。

It was all due to permissions in the dagger folder inside of my jar. 这都是由于我jar里的dagger文件夹中的权限所致。 All the other folders (eg com, org, mozilla) had 755, but not the dagger folder. 所有其他文件夹(例如com,org,mozilla)都有755,但没有dagger文件夹。 I unzipped my jar, ran two commands to convert the directories to 755 and the files to 644, then I zipped it back up. 我解压缩了jar,运行了两个命令,将目录转换为755,将文件转换为644,然后将其压缩回来。

The commands for changing the permissions: 更改权限的命令:

From inside the unzipped directory:
find . -type f -exec chmod 644 {} +
find . -type d -exec chmod 755 {} +

I don't know why it is different to the other directories when Bazel is building it. 我不知道在Bazel构建它时为什么它与其他目录不同。 But that is the problem. 但这就是问题所在。


For future Bazel searchers, here is the genrule I'm now using: 对于将来的Bazel搜索者,以下是我现在使用的genrule:

genrule(
  name = "target-aws",
  srcs = ["target_deploy.jar"],
  outs = ["target-aws.jar"],
  cmd = """
  unzip -q $< -d t
  cd t
  find . -type f -exec chmod 644 {} +
  find . -type d -exec chmod 755 {} +
  zip ../$@ -q -r .
  rm -rf t
  """
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 由java.lang.NoClassDefFoundError和ClassNotFoundException引起的错误 - Error caused by java.lang.NoClassDefFoundError and ClassNotFoundException NoClassDefFoundError:…由ClassNotFoundException引起 - NoClassDefFoundError: … Caused by ClassNotFoundException AWS Lambda Java 错误:ClassNotFoundException - AWS Lambda Java Error: ClassNotFoundException 将 Java Web 应用程序部署到 Heroku:由 ClassNotFoundException 引起的 NoClassDefFoundError - deploying java web app to heroku: NoClassDefFoundError caused by ClassNotFoundException ClassNotFoundException 导致的线程“主”java.lang.NoClassDefFoundError 中的异常 - Exception in thread "main" java.lang.NoClassDefFoundError caused by ClassNotFoundException NoClassDefFoundError原因:java.lang.ClassNotFoundException:junit.textui.ResultPrinter - NoClassDefFoundError Caused by: java.lang.ClassNotFoundException: junit.textui.ResultPrinter 如何解决ClassNotFoundException引起的NoClassDefFoundError? - How to solve a NoClassDefFoundError caused by ClassNotFoundException? loadClass抛出由ClassNotFoundException引起的NoClassDefFoundError - loadClass throws NoClassDefFoundError caused by ClassNotFoundException 'java.lang.NoClassDefFoundError java.lang.ClassNotFoundException 导致的 Ljava/util/Base64 解析失败 未找到 class “java.util.Base64” - 'java.lang.NoClassDefFoundError Failed resolution of Ljava/util/Base64 caused by java.lang.ClassNotFoundException Didn't find class "java.util.Base64" 无法在本地调用 Java 上的 Lambda AWS - Cannot invoke Lambda AWS on java locally
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM