Giraph Shortest Paths示例ClassNotFoundException

时间:2012-05-22 11:09:24

标签: hadoop classnotfoundexception shortest-path giraph

我正试图从giraph孵化器(https://cwiki.apache.org/confluence/display/GIRAPH/Shortest+Paths+Example)运行最短路径示例。但是,我没有从giraph - * - dependencies.jar执行示例,而是创建了自己的作业jar。当我创建一个如示例中所示的Job文件时,我得到了

java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.Test$SimpleShortestPathsVertexInputFormat

然后我移动了内部类(SimpleShortestPathsVertexInputFormat和SimpleShortestPathsVertexOutputFormat)来分离文件并重命名它们以防万一(SimpleShortestPathsVertexInputFormat_v2,SimpleShortestPathsVertexOutputFormat_v2);类不再是静态的了。这解决了SimpleShortestPathsVertexInputFormat_v2找不到类的问题,但是我仍然得到SimpleShortestPathsVertexOutputFormat_v2的相同错误。下面是我的堆栈跟踪。

INFO mapred.JobClient: Running job: job_201205221101_0003
INFO mapred.JobClient:  map 0% reduce 0%
INFO mapred.JobClient: Task Id : attempt_201205221101_0003_m_000005_0, Status : FAILED
    java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.utils.SimpleShortestPathsVertexOutputFormat_v2
            at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:898)
            at org.apache.giraph.graph.BspUtils.getVertexOutputFormatClass(BspUtils.java:134)
            at org.apache.giraph.bsp.BspOutputFormat.getOutputCommitter(BspOutputFormat.java:56)
            at org.apache.hadoop.mapred.Task.initialize(Task.java:490)
            at org.apache.hadoop.mapred.MapTask.run(MapTask.java:352)
            at org.apache.hadoop.mapred.Child$4.run(Child.java:259)
            at java.security.AccessController.doPrivileged(Native Method)
            at javax.security.auth.Subject.doAs(Subject.java:415)
            at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1059)
            at org.apache.hadoop.mapred.Child.main(Child.java:253)
    Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.test.giraph.utils.SimpleShortestPathsVertexOutputFormat_v2
            at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:866)
            at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:890)
            ... 9 more

我检查了我的工作罐,所有课程都在那里。此外,我在伪分布模式下使用hadoop 0.20.203。我开始工作的方式如下所示。

hadoop jar giraphJobs.jar org.test.giraph.Test -libjars /path/to/giraph-0.2-SNAPSHOT-jar-with-dependencies.jar /path/to/input /path/to/output 0 3

我也为giraph - * - dependencies.jar定义了HADOOP_CLASSPATH。我可以毫无问题地运行PageRankBenchmark示例(直接来自giraph - * - dependencies.jar),并且shortes路径示例也可以工作(也可以直接来自giraph - * - dependencies.jar)。其他hadoop工作没有问题(在某些地方我已经阅读过以测试我的"集群"是否正常工作)。有没有人遇到类似的问题?任何帮助将不胜感激。


解决方案(很抱歉发布这样的内容,但我无法回答我自己的问题几个小时)

要解决此问题,我必须将我的Job jar添加到-libjars(不会更改HADOOP_CLASSPATH所在的位置)。启动工作的命令现在看起来像这样。

hadoop jar giraphJobs.jar org.test.giraph.Test -libjars /path/to/giraph-0.2-SNAPSHOT-jar-with-dependencies.jar,/path/to/job.jar /path/to/input /path/to/output 0 3

罐子列表必须以逗号分隔。虽然这解决了我的问题。我仍然很好奇为什么我必须把我的工作罐作为一个"类路径"参数?谁能解释一下这背后的理性是什么?我觉得很奇怪(至少可以说)调用我的工作罐然后再将它作为一个"类路径"罐。我对这个解释很好奇。

1 个答案:

答案 0 :(得分:3)

我找到了解决问题的替代程序解决方案。 我们需要以下列方式修改run()方法 -

...
@Override
public int run(String[] argArray) throws Exception {
    Preconditions.checkArgument(argArray.length == 4,
        "run: Must have 4 arguments <input path> <output path> " +
        "<source vertex id> <# of workers>");

    GiraphJob job = new GiraphJob(getConf(), getClass().getName());
    // This is the addition - it will make hadoop look for other classes in the same     jar that contains this class
    job.getInternalJob().setJarByClass(getClass());
    job.setVertexClass(getClass());
    ...
}

setJarByClass()将使hadoop在包含getClass()返回的类的同一个jar中查找缺少的类,并且我们不需要将作业jar名称单独添加到-libjars选项。