我有一个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
.
1条答案
按热度按时间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加载它们。