【问题标题】:Hadoop ApplicationClassLoader can't find classHadoop ApplicationClassLoader 找不到类
【发布时间】:2021-02-12 08:19:01
【问题描述】:

我尝试在 GCP Dataproc 集群上运行 MapReduce 作业:

gcloud dataproc jobs submit hadoop \
    --cluster="$cluster" \
    --jar foo.jar \
    --properties=mapreduce.job.classloader=true \
    ....

当我运行我的工作时,我收到了这个错误:

Error: java.lang.ClassNotFoundException: org.w3c.dom.ElementTraversal
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at org.apache.hadoop.util.ApplicationClassLoader.loadClass(ApplicationClassLoader.java:189)
    at org.apache.hadoop.util.ApplicationClassLoader.loadClass(ApplicationClassLoader.java:157)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at org.apache.hadoop.util.ApplicationClassLoader.loadClass(ApplicationClassLoader.java:176)
    at org.apache.hadoop.util.ApplicationClassLoader.loadClass(ApplicationClassLoader.java:157)
    <xerces code>
    <my mapper code>
    at org.apache.hadoop.mapreduce.lib.input.DelegatingMapper.run(DelegatingMapper.java:55)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:798)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:346)
    at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1762)
    at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:168)

jar 是由 Maven shade 插件创建的,并且该类在其中:

jar -tf foo.jar | grep ElementTraversal
org/w3c/dom/ElementTraversal.class

一些谷歌搜索建议将 xml-apis v1.4.01 作为依赖项包括在内,我有,但它没有任何区别,而且它已经是一个传递依赖项。根据我的阅读,mapreduce.job.classloader=true 属性告诉 Hadoop 更喜欢我的工作 jar 中的类,而不是 Hadoop 发行版,这似乎是ApplicationClassLoader 的重点。

【问题讨论】:

    标签: hadoop classloader classnotfoundexception


    【解决方案1】:

    事实证明,Hadoop 遵循系统类加载器的系统类。现代 Java 附带 xml-apis(但版本较旧),因此它被标记为系统类。

    我找到了与mapreduce.job.classloader 配对的mapreduce.job.classloader.system.classes 标志:

    用于覆盖作业类加载器的系统类的默认定义。系统类是以逗号分隔的模式列表,指示在启用 mapreduce.job.classloader 时是否从系统类路径加载类,而不是从用户提供的 JAR 加载。

    https://hadoop.apache.org/docs/r2.7.1/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml

    将此添加到我的属性中解决了该问题。它从 hadoop 考虑的系统类中排除 org.w3c.dom 类,并从我的作业 jar 中加载它们。

    mapreduce.job.classloader.system.classes=-org.w3c.dom.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多