您的位置:首页 > 移动开发

java.lang.RuntimeException: java.lang.ClassNotFoundException: xxxxMapper

2012-11-09 16:44 309 查看

解决方法

最近做hadoop集群试验,用的hadoop1.0.2,遇到这么个问题,将写好的jar包,放到linux上后,执行hadoop jar hadoopTest.jar test.XXXCount input output 后,
运行时,会报下面的警告

WARN mapred.JobClient: No job jar file set.
User classes may not be found. See JobConf(Class)or JobConf#setJar(String).

之后就会报错:

java.lang.RuntimeException: java.lang.ClassNotFoundException: xxxxMapper

虽然从网上查了很多,基本都是写需要在声明job时,加上job.setJarByClass(WordCount.class);

但是我加上之后还是运行不对,之后看源码后才发现,有一个判断,是判断"jar".equals(url.getProtocol())但是,这个永远是在我debug后得知,url.getProtocol()永远是“file”,不是“jar”,原因我想可能是hadoop jar的流程(详见下面转的hadoop jar流程)中,这条命令,会将jar解压到/home/hadoop/hadoop-fs/dfs/temp/hadoop- unjarxxxxxx这样的目录下,所以程序执行时,通过class名称,根本找不到jar包。当然也可能是这个1.0.2的版本有bug,或者我使用的方法不对。

我现在的解决办法是在Configuration里加上配置,将需要用到的jar通过配置加进来:conf.set("mapred.jar", "/home/test/hadoopTest.jar");

还有几种方法,没有试,一个是在mapred-site.xml配置文件中加上property,另外一个就是在<<基于Hadoop实现通用的并行任务处理>>中提到项目依赖包可通过Hadoop的DistributedCache功能来保证分布运行。同样,我们也可以利用它将入口类所在的Jar包加入到DistributedCache中,同时避免设置mapred.jar选项(调用Job类的setJarByClass方法做到)。这样就少了两次copy的过程。

参考:【转】hadoop jar xxxx.jar的流程

搞清楚 hadoop jar xxxx.jar 执行的流程: jar文件是如何分发的

JobClient(不一定是hadoop集群的节点)利用bin/hadoop脚本运行jar包,以hadoop-0.20.2-examples.jar为例子:

hadoop jar hadoop-0.20.2-examples.jar [class name]的实质是:

1.利用hadoop这个脚本启动一个jvm进程;

2.jvm进程去运行org.apache.hadoop.util.RunJar这个java类;3.org.apache.hadoop.util.RunJar解压hadoop-0.20.2-examples.jar到hadoop.tmp.dir/hadoop-unjar*/目录下;

4.org.apache.hadoop.util.RunJar动态的加载并运行Main-Class或指定的Class;5.Main-Class或指定的Class中设定Job的各项属性

6.提交job到JobTracker上并监视运行情况。



注意:以上都是在jobClient上执行的。

运行jar文件的时候,jar会被解压到hadoop.tmp.dir/hadoop-unjar*/目录下(如:/home/hadoop/hadoop-fs/dfs/temp/hadoop- unjar693919842639653083,注意:这个目录是JobClient的目录,不是JobTracker的目录)。解压后的文件为:

drwxr-xr-x 2 hadoop hadoop 4096 Jul 30 15:40 META-INF

drwxr-xr-x 3 hadoop hadoop 4096 Jul 30 15:40 org

有图有真相:



提交job的实质是:

生成${job-id}/job.xml文件到hdfs://${mapred.system.dir}
/(比如hdfs://bcn152:9990/home/hadoop/hadoop-fs/dfs/temp/mapred/system/job_201007301137_0012/job.xml),job的描述包括jar文件的路径map|reduce类路径等等.

上传${job-id}/job.jar文件到hdfs://${mapred.system.dir}/(比如hdfs://bcn152:9990/home/hadoop/hadoop-fs/dfs/temp/mapred/system/job_201007301137_0012/job.jar)

有图有真相:



生成job之后,通过static JobClient.runJob()就会向jobTracker提交job:

JobClient jc = new JobClient(job);

RunningJob rj = jc.submitJob(job);

之后JobTracker就会调度此job,

提交job之后,使用下面的代码获取job的进度:

try {

if (!jc.monitorAndPrintJob(job, rj)) {

throw new IOException("Job failed!");

}

} catch (InterruptedException ie) {

Thread.currentThread().interrupt();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐