Hadoop ApplicationClassLoader 找不到类



我有一个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插件创建的,这个类就在里面:

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

一些谷歌建议包括xml-api v1.4.01作为一个依赖项,我这样做了,但这没有什么区别,它已经是一个可传递的依赖项。从我读到的,mapreduce.job.classloader=true属性告诉Hadoop更喜欢我工作的jar中的类,而不是Hadoop发行版,这似乎是ApplicationClassLoader的全部意义。

事实证明,对于系统类,Hadoop遵从系统类加载器。现代Java附带xml-api(但是旧版本),因此它被标记为系统类。

我找到了与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类,并从我的job jar中加载它们。

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

相关内容

  • 没有找到相关文章

最新更新