我有一个hadoop作业,其中Map器必须使用外部jar。
我试图将这个jar传递给Map程序的jvm
通过hadoop命令上的-libjars参数
hadoop jar mrrunner.jar DAGMRRunner -libjars <path_to_jar>/colt.jar
通过job.addfiletoclasspath
job.addFileToClassPath(new Path("<path_to_jar>/colt.jar"));
在hadoop\u类路径上。
g1mihai@hydra:/home/g1mihai/$ echo $HADOOP_CLASSPATH
<path_to_jar>/colt.jar
这些方法都不管用。这是我得到的堆栈跟踪。它抱怨缺少的类是sparsedoublematrix1d,它位于colt.jar中。
让我知道如果我应该提供任何额外的调试信息。谢谢。
15/02/14 16:47:51 INFO mapred.MapTask: Starting flush of map output
15/02/14 16:47:51 INFO mapred.LocalJobRunner: map task executor complete.
15/02/14 16:47:51 WARN mapred.LocalJobRunner: job_local368086771_0001
java.lang.Exception: java.lang.NoClassDefFoundError: Lcern/colt/matrix/impl/SparseDoubleMatrix1D;
at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522)
Caused by: java.lang.NoClassDefFoundError: Lcern/colt/matrix/impl/SparseDoubleMatrix1D;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2499)
at java.lang.Class.getDeclaredField(Class.java:1951)
at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1659)
at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:72)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:480)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:468)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:468)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:365)
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:602)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at BoostConnector.ConnectCalculateBoost(BoostConnector.java:39)
at DAGMapReduceSearcher$Map.map(DAGMapReduceSearcher.java:46)
at DAGMapReduceSearcher$Map.map(DAGMapReduceSearcher.java:22)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:145)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:784)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
at org.apache.hadoop.mapred.LocalJobRunner$Job$MapTaskRunnable.run(LocalJobRunner.java:243)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: cern.colt.matrix.impl.SparseDoubleMatrix1D
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 28 more
3条答案
按热度按时间nbnkbykc1#
使用分布式缓存-您可以在缓存中有任何可执行文件或小引用文件,并在mr作业中使用它们。
https://hadoop.apache.org/docs/r1.2.1/api/org/apache/hadoop/filecache/distributedcache.html
运行mr作业有两种方法,一种是在运行时使用类名,另一种是在导出jar时使用主类。
zpf6vheq2#
我相信这个问题应该得到一个详细的回答,我昨天被困在这个问题上,浪费了很多时间。我希望这个答案能帮助每一个碰巧遇到这个问题的人。有两种方法可以解决此问题:
将外部jar(依赖项jar)作为应用程序jar文件的一部分。您可以使用eclipse轻松地做到这一点。此选项的缺点是会使应用程序jar膨胀,并且Map的作业需要更多的时间来执行。每次你的依赖版本改变时,你将不得不重新编译应用程序等。最好不要走这条路。
使用“hadoop classpath”——在命令行上运行命令“hadoop classpath”,然后找到一个合适的文件夹并将jar文件复制到该位置,hadoop将从那里获取依赖关系。这不适用于cloudera等,因为您可能没有将文件复制到hadoop类路径文件夹的读/写权限。
我使用的选项是使用hadoopjar命令指定-libjars。首先确保编辑驱动程序类:
现在编辑“hadoop jar”命令,如下所示:
现在让我们了解下面发生了什么。基本上,我们通过实现工具接口来处理新的命令行参数。toolrunner用于运行实现工具接口的类。它与genericoptionsparser一起工作,解析通用hadoop命令行参数并修改工具的配置。
在main()中调用
ToolRunner.run(new Configuration(), new myDriverClass(), args)
-在使用给定的泛型参数进行分析之后,将按tool.run(字符串[])运行给定的工具。它使用给定的配置,如果为null,则构建一个配置,然后使用可能修改的conf版本设置工具的配置。现在在run方法中,当我们调用getconf()时,我们得到了配置的修改版本。所以确保你的代码中有下面一行。如果您实现了其他所有功能,并且仍然使用configuration conf=new configuration(),则什么都不起作用。
wb1gzix03#
我用了这个:
它在hadoop3.2.0中运行正常。