hadoop应用程序类加载器找不到类

aydmsdu9  于 2021-07-15  发布在  Hadoop
关注(0)|答案(1)|浏览(429)

我有一个mapreduce作业正在gcp dataproc群集上运行:

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

一些google建议将xmlapisv1.4.01作为一个依赖项,我也这样做过,但这没有什么区别,它已经是一个可传递的依赖项了。据我所知 mapreduce.job.classloader=true 属性告诉hadoop更喜欢myjob的jar中的类,而不是hadoop发行版,这似乎是本文的重点 ApplicationClassLoader .

sbdsn5lh

sbdsn5lh1#

事实证明,hadoop遵从系统类的系统类加载器。现代java附带了xmlapi(但是较旧的版本),因此它被标记为系统类。
我找到了 mapreduce.job.classloader.system.classes 与之配对的标志 mapreduce.job.classloader :
用于重写作业类加载器的系统类的默认定义。系统类是一个以逗号分隔的模式列表,指示在启用mapreduce.job.classloader时是否从系统类路径而不是从用户提供的jar加载类。
https://hadoop.apache.org/docs/r2.7.1/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
将此添加到我的属性中修复了问题。它排除了 org.w3c.dom hadoop所考虑的系统类中的类,并从我的job jar加载它们。

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

相关问题