java - 如何将外部 jar 添加到 hadoop 作业?

标签 java hadoop mapreduce noclassdeffounderror

我有一个 Hadoop 作业,其中映射器必须使用外部 jar。

我试图将这个 jar 传递给映射器的 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_CLASSPATH 上。

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

最佳答案

我相信这个问题值得详细回答,昨天我被这个问题困住了,浪费了很多时间。我希望这个答案可以帮助每个碰巧遇到这个问题的人。有几个选项可以解决此问题:

  1. 将外部 jar(依赖 JAR)作为应用程序 jar 文件的一部分。您可以使用 Eclipse 轻松完成此操作。此选项的缺点是它会使您的应用程序 jar 膨胀,并且您的 MapRed 作业将花费更多时间来执行。每次您的依赖版本发生变化时,您都必须重新编译应用程序等。最好不要走这条路。

  2. 使用“Hadoop 类路径”- 在命令行上运行命令“hadoop 类路径”,然后找到合适的文件夹并将您的 jar 文件复制到该位置,hadoop 将从那里获取依赖项。这不适用于 CloudEra 等,因为您可能没有将文件复制到 hadoop 类路径文件夹的读/写权限。

  3. 我使用的选项是使用 Hadoop jar 命令指定 -LIBJARS。首先确保您编辑了您的驱动程序类:

    public class myDriverClass extends Configured implements Tool {
    
      public static void main(String[] args) throws Exception {
         int res = ToolRunner.run(new Configuration(), new myDriverClass(), args);
         System.exit(res);
      }
    
      public int run(String[] args) throws Exception
      {
    
        // Configuration processed by ToolRunner 
        Configuration conf = getConf();
        Job job = new Job(conf, "My Job");
    
        ...
        ...
    
        return job.waitForCompletion(true) ? 0 : 1;
      }
    }
    

现在编辑“hadoop jar”命令,如下所示:

hadoop jar YourApplication.jar [myDriverClass] args -libjars path/to/jar/file

现在让我们了解下面发生的事情。基本上我们通过实现 TOOL Interface 来处理新的命令行参数。 . ToolRunner 用于运行实现 Tool 接口(interface)的类。它与 GenericOptionsParser 结合使用解析通用 hadoop 命令行参数并修改工具的配置。

在我们的 Main() 中,我们调用 ToolRunner.run(new Configuration(), new myDriverClass(), args) - 这通过 Tool.run(String[]) 运行给定的工具, 在使用给定的通用参数解析之后。它使用给定的配置,如果它为空,则构建一个,然后使用可能修改的 conf 版本设置工具的配置。

现在在 run 方法中,当我们调用 getConf() 时,我们将获得配置的修改版本。 因此请确保您的代码中包含以下行。如果您实现所有其他内容并仍然使用 Configuration conf = new Configuration(),则没有任何效果。

Configuration conf = getConf();

关于java - 如何将外部 jar 添加到 hadoop 作业?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28520821/

相关文章:

hadoop - 在 talend 大数据中创建与 hadoop 的连接时出现问题

当文件格式为自定义格式时,Hadoop MultipleOutputs 不会写入多个文件

java - 如何将 Hadoop MapReduce 作业实现为非 Map/Reduce,即使没有任何意义?

java - 如何检查公钥是否与私钥匹配?

Java 将字段反射分配为 null 导致 IllegaArgumentException

hadoop - MapReduce中多个输入路径中的错误

java - 优化PIG中的过滤功能

javascript - Couch db 日期和溢出

java - 轮询 Pod 的就绪状态

java - 是否支持 log4j.properties 文件包含?