问题
运行mapreduce 报mapper类(内部静态类) java.lang.ClassNotFoundException
代码中用job.setJarByClass(ExampleJob.class);
来设置主类的,没设置引用其他jar包
原因
这样设置相当于只给mapreduce任务设置了一个要加载的类,要用的mapper类没加载。
解决
第一步
如果像我这样mapper类写成静态内部类,可以在打包的时候把内部类也一起打包进jar
$ javac -cp $(hbase classpath) MapReduceMainClass.java
$ jar cf MapReduceMainClass.jar MapReduceMainClass*.class
其中,$(hbase classpath)会返回HBase类路径,*.class匹配HBaseDeleteMapReduce类及其内部静态类HBaseDeleteMapper的所有编译后的类文件。
jar cf
命令用于创建一个JAR文件。JAR文件是Java中的一种归档文件格式,可以用于存储Java类、资源文件、库文件以及其他类型的文件。
jar cf命令的语法如下:
jar cf <jar-file> <file1> <file2> ...
其中,是要创建的JAR文件的名称,、等参数是要添加到JAR文件中的文件或目录的名称。如果指定的是目录,则该目录中的所有文件和子目录都将被添加到JAR文件中。
第二步
在执行MapReduce作业之前,你需要将HBaseDeleteMapReduce.jar文件添加到Hadoop类路径中,可以使用下面的命令:
$ export HADOOP_CLASSPATH=/path/to/MapReduceMainClass.jar
再使用hadoop jar命令来启动MapReduce作业:
$ hadoop jar MapReduceMainClass.jar
mr任务依赖多个jar包
在使用Hadoop运行MapReduce作业时,如果你的作业依赖于多个JAR文件,你需要确保这些JAR文件都在作业的类路径中。有几种方式可以实现这一点:
方式1
将所有的依赖JAR文件打包成一个JAR文件。这是最常见的方式,你可以使用jar cf命令将所有依赖的JAR文件打包成一个大JAR文件,并将该JAR文件添加到作业的类路径中。
$ jar cf mylib.jar /path/to/dependency1.jar /path/to/dependency2.jar ...
在提交作业时,将该JAR文件添加到类路径中:
$ hadoop jar myjob.jar -libjars /path/to/mylib.jar <input> <output>
注意,你需要将JAR文件的路径传递给-libjars选项,该选项接受一个以逗号分隔的JAR文件列表。
方式2
- 将依赖JAR文件添加到Hadoop类路径中。你可以将依赖的JAR文件拷贝到Hadoop类路径中(例如,$HADOOP_HOME/lib目录),这样它们就会被自动加载。(这个我理解应该是每个运行mr任务的机器上吧)
方式3
- 使用-classpath选项指定类路径。你可以使用-classpath选项将所有依赖JAR文件的路径以逗号分隔的形式传递给作业提交命令:
$ hadoop jar myjob.jar -classpath /path/to/dependency1.jar:/path/to/dependency2.jar <input> <output>
注意,你需要使用冒号分隔不同的路径。
总之,在设置作业的类路径时,你需要确保所有依赖的JAR文件都在该路径中。
补充:-libjars
VS -classpath
-libjars
和 -classpath
都是用来指定依赖的jar包的参数,但它们在用法和作用上有一些区别。
-libjars
是用来指定任务运行所需的jar包的位置,它将在运行时将这些jar包分发到所有的Task节点上,使得Task节点可以加载这些jar包中的类和资源。使用该参数时,可以指定多个jar包,它们之间使用逗号分隔。
-classpath
是用来指定运行任务所需的类路径的参数。类路径指的是JVM用来搜索类和资源的路径,通常是包含一些jar包和目录的路径。使用该参数时,可以指定多个目录和jar包,它们之间使用分号(Windows)或冒号(Unix/Linux)分隔。
总的来说,-libjars
主要用于指定任务运行所需的jar包,而 -classpath
主要用于指定任务运行时需要的类路径,包括一些自定义的类或第三方依赖的jar包。两者通常一起使用, -libjars 用于指定所有需要的jar包, -classpath 则用于指定自定义类和其他额外的jar包。
如果任务代码中使用了第三方依赖的jar包,而这些依赖的jar包不在Task节点上,则会抛出ClassNotFoundException
或NoClassDefFoundError
等类加载异常。为了避免这种情况,可以通过-libjars
参数指定所有需要的jar包,它们将被分发到所有的Task节点上。